From fdade31890509d997bdcf345494291195db04586 Mon Sep 17 00:00:00 2001 From: Steve Salevan Date: Mon, 16 Jun 2025 17:50:46 -0400 Subject: [PATCH 1/5] Adds prettyTrace evaluator setting to support indented, multi-line trace() output --- bench/src/jmh/java/org/pkl/core/ListSort.java | 3 +- docs/src/test/kotlin/DocSnippetTests.kt | 1 + .../src/main/kotlin/org/pkl/cli/CliRepl.kt | 1 + .../org/pkl/cli/repl/ReplMessagesTest.kt | 3 +- .../org/pkl/commons/cli/CliBaseOptions.kt | 5 ++- .../src/main/java/org/pkl/core/Analyzer.java | 8 +++- .../java/org/pkl/core/EvaluatorBuilder.java | 17 +++++++- .../main/java/org/pkl/core/EvaluatorImpl.java | 6 ++- .../core/ast/expression/unary/TraceNode.java | 15 +++++-- .../PklEvaluatorSettings.java | 19 +++++++-- .../java/org/pkl/core/project/Project.java | 13 +++++-- .../java/org/pkl/core/repl/ReplServer.java | 6 ++- .../org/pkl/core/runtime/StdLibModule.java | 5 ++- .../java/org/pkl/core/runtime/VmContext.java | 11 +++++- .../projects/evaluatorSettings/PklProject | 1 + .../evaluatorSettings/prettyTraces.pkl | 18 +++++++++ .../evaluatorSettings/prettyTraces.err | 39 +++++++++++++++++++ .../test/kotlin/org/pkl/core/AnalyzerTest.kt | 4 ++ .../kotlin/org/pkl/core/ReplServerTest.kt | 1 + .../org/pkl/core/project/ProjectTest.kt | 1 + .../java/org/pkl/gradle/task/BasePklTask.java | 3 +- .../java/org/pkl/gradle/task/ModulesTask.java | 3 +- .../kotlin/org/pkl/server/BinaryEvaluator.kt | 2 + .../src/main/kotlin/org/pkl/server/Server.kt | 1 + .../pkl/server/BinaryEvaluatorSnippetTests.kt | 1 + .../org/pkl/server/BinaryEvaluatorTest.kt | 1 + stdlib/EvaluatorSettings.pkl | 4 ++ 27 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/prettyTraces.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/prettyTraces.err diff --git a/bench/src/jmh/java/org/pkl/core/ListSort.java b/bench/src/jmh/java/org/pkl/core/ListSort.java index 1324b53ba..c3b2accca 100644 --- a/bench/src/jmh/java/org/pkl/core/ListSort.java +++ b/bench/src/jmh/java/org/pkl/core/ListSort.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -51,6 +51,7 @@ public class ListSort { null, IoUtils.getCurrentWorkingDir(), StackFrameTransformers.defaultTransformer, + false, false); private static final List list = new ArrayList<>(100000); diff --git a/docs/src/test/kotlin/DocSnippetTests.kt b/docs/src/test/kotlin/DocSnippetTests.kt index b8e3f6a2b..6265f49ed 100644 --- a/docs/src/test/kotlin/DocSnippetTests.kt +++ b/docs/src/test/kotlin/DocSnippetTests.kt @@ -97,6 +97,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine = mapOf(), + + /** Whether to render calls to trace() as an indented, multi-line string. */ + val prettyTraces: Boolean = false, ) { companion object { diff --git a/pkl-core/src/main/java/org/pkl/core/Analyzer.java b/pkl-core/src/main/java/org/pkl/core/Analyzer.java index 345e9e88a..6d5053a4a 100644 --- a/pkl-core/src/main/java/org/pkl/core/Analyzer.java +++ b/pkl-core/src/main/java/org/pkl/core/Analyzer.java @@ -46,6 +46,7 @@ public class Analyzer { private final @Nullable DeclaredDependencies projectDependencies; private final ModuleResolver moduleResolver; private final HttpClient httpClient; + private final boolean prettyTraces; public Analyzer( StackFrameTransformer transformer, @@ -54,7 +55,8 @@ public Analyzer( Collection moduleKeyFactories, @Nullable Path moduleCacheDir, @Nullable DeclaredDependencies projectDependencies, - HttpClient httpClient) { + HttpClient httpClient, + boolean prettyTraces) { this.transformer = transformer; this.color = color; this.securityManager = securityManager; @@ -62,6 +64,7 @@ public Analyzer( this.projectDependencies = projectDependencies; this.moduleResolver = new ModuleResolver(moduleKeyFactories); this.httpClient = httpClient; + this.prettyTraces = prettyTraces; } /** @@ -115,7 +118,8 @@ private Context createContext() { projectDependencies == null ? null : new ProjectDependenciesManager( - projectDependencies, moduleResolver, securityManager))); + projectDependencies, moduleResolver, securityManager), + prettyTraces)); }); } } diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java index aa7ae8dd2..97ee12258 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java @@ -67,6 +67,8 @@ public final class EvaluatorBuilder { private @Nullable DeclaredDependencies dependencies; + private boolean prettyTraces = false; + private EvaluatorBuilder() {} /** @@ -454,6 +456,17 @@ public EvaluatorBuilder setProjectDependencies(DeclaredDependencies dependencies return this.dependencies; } + /** Sets whether calls to trace() produce indented, multi-line output. */ + public EvaluatorBuilder setPrettyTraces(boolean prettyTraces) { + this.prettyTraces = prettyTraces; + return this; + } + + /** Returns whether calls to trace() produce indented, multi-line output. */ + public boolean getPrettyTraces() { + return this.prettyTraces; + } + /** * Given a project, sets its dependencies, and also applies any evaluator settings if set. * @@ -517,6 +530,7 @@ public EvaluatorBuilder applyFromProject(Project project) { procs.computeIfAbsent(entry.getValue(), ExternalReaderProcess::of))); } } + this.prettyTraces = Boolean.TRUE.equals(settings.prettyTraces()); return this; } @@ -543,6 +557,7 @@ public Evaluator build() { timeout, moduleCacheDir, dependencies, - outputFormat); + outputFormat, + prettyTraces); } } diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java index 2d607e6c0..3d3ce3729 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java @@ -80,7 +80,8 @@ public EvaluatorImpl( @Nullable Duration timeout, @Nullable Path moduleCacheDir, @Nullable DeclaredDependencies projectDependencies, - @Nullable String outputFormat) { + @Nullable String outputFormat, + boolean prettyTraces) { securityManager = manager; frameTransformer = transformer; @@ -108,7 +109,8 @@ public EvaluatorImpl( projectDependencies == null ? null : new ProjectDependenciesManager( - projectDependencies, moduleResolver, securityManager))); + projectDependencies, moduleResolver, securityManager), + prettyTraces)); }); this.timeout = timeout; // NOTE: would probably make sense to share executor between evaluators diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java index 649920ae4..3fa14546f 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -24,7 +24,11 @@ public final class TraceNode extends ExpressionNode { @Child private ExpressionNode valueNode; - private final VmValueRenderer renderer = VmValueRenderer.singleLine(1000000); + private static final int MAX_RENDERER_LENGTH = 1000000; + + private final VmValueRenderer singleLineRenderer = + VmValueRenderer.singleLine(MAX_RENDERER_LENGTH); + private final VmValueRenderer multiLineRenderer = VmValueRenderer.multiLine(MAX_RENDERER_LENGTH); public TraceNode(SourceSection sourceSection, ExpressionNode valueNode) { super(sourceSection); @@ -48,7 +52,12 @@ private void doTrace(Object value, VmContext context) { } var sourceSection = valueNode.getSourceSection(); - var renderedValue = renderer.render(value); + String renderedValue; + if (context.getPrettyTraces()) { + renderedValue = multiLineRenderer.render(value); + } else { + renderedValue = singleLineRenderer.render(value); + } var message = (sourceSection.isAvailable() ? sourceSection.getCharacters() : " patterns) { @@ -231,7 +234,15 @@ private int hashPatterns(@Nullable List patterns) { public int hashCode() { var result = Objects.hash( - externalProperties, env, color, noCache, moduleCacheDir, timeout, rootDir, http); + externalProperties, + env, + color, + noCache, + moduleCacheDir, + timeout, + rootDir, + http, + prettyTraces); result = 31 * result + hashPatterns(allowedModules); result = 31 * result + hashPatterns(allowedResources); return result; diff --git a/pkl-core/src/main/java/org/pkl/core/project/Project.java b/pkl-core/src/main/java/org/pkl/core/project/Project.java index ab3ff31a0..f3434dc9c 100644 --- a/pkl-core/src/main/java/org/pkl/core/project/Project.java +++ b/pkl-core/src/main/java/org/pkl/core/project/Project.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -197,7 +197,8 @@ private static List> findImportCycle(ModuleSource moduleSource) { builder.getModuleKeyFactories(), builder.getModuleCacheDir(), builder.getProjectDependencies(), - builder.getHttpClient()); + builder.getHttpClient(), + builder.getPrettyTraces()); var importGraph = analyzer.importGraph(moduleSource.getUri()); var ret = ImportGraphUtils.findImportCycles(importGraph); // we only care about cycles in the same scheme as `moduleSource` @@ -511,7 +512,8 @@ public EvaluatorSettings( @Nullable Path moduleCacheDir, @Nullable List modulePath, @Nullable Duration timeout, - @Nullable Path rootDir) { + @Nullable Path rootDir, + @Nullable Boolean prettyTraces) { this.delegate = new PklEvaluatorSettings( externalProperties, @@ -526,7 +528,8 @@ public EvaluatorSettings( rootDir, null, null, - null); + null, + prettyTraces); } @Deprecated(forRemoval = true) @@ -610,6 +613,8 @@ public String toString() { + delegate.timeout() + ", rootDir=" + delegate.rootDir() + + ", prettyTraces=" + + delegate.prettyTraces() + '}'; } } diff --git a/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java b/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java index a117478d5..11a847f88 100644 --- a/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java +++ b/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java @@ -82,7 +82,8 @@ public ReplServer( @Nullable String outputFormat, Path workingDir, StackFrameTransformer frameTransformer, - boolean color) { + boolean color, + boolean prettyTraces) { this.workingDir = workingDir; this.securityManager = securityManager; @@ -114,7 +115,8 @@ public ReplServer( moduleCacheDir, outputFormat, packageResolver, - projectDependenciesManager)); + projectDependenciesManager, + prettyTraces)); }); language = languageRef.get(); } diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java b/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java index 28bfe592f..f53f57458 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -49,7 +49,8 @@ protected static void loadModule(URI uri, VmTyped instance) { null, null, null, - null)); + null, + false)); var language = VmLanguage.get(null); var moduleKey = ModuleKeys.standardLibrary(uri); var source = VmUtils.loadSource((ResolvedModuleKey) moduleKey); diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java b/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java index b691de165..75bb9dedc 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -50,6 +50,7 @@ public static final class Holder { private final ModuleCache moduleCache; private final @Nullable PackageResolver packageResolver; private final @Nullable ProjectDependenciesManager projectDependenciesManager; + private final boolean prettyTraces; public Holder( StackFrameTransformer frameTransformer, @@ -63,7 +64,8 @@ public Holder( @Nullable Path moduleCacheDir, @Nullable String outputFormat, @Nullable PackageResolver packageResolver, - @Nullable ProjectDependenciesManager projectDependenciesManager) { + @Nullable ProjectDependenciesManager projectDependenciesManager, + boolean prettyTraces) { this.frameTransformer = frameTransformer; this.securityManager = securityManager; @@ -84,6 +86,7 @@ public Holder( moduleCache = new ModuleCache(); this.packageResolver = packageResolver; this.projectDependenciesManager = projectDependenciesManager; + this.prettyTraces = prettyTraces; } } @@ -143,4 +146,8 @@ public Map getExternalProperties() { public @Nullable ProjectDependenciesManager getProjectDependenciesManager() { return holder.projectDependenciesManager; } + + public boolean getPrettyTraces() { + return holder.prettyTraces; + } } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject index 1040058e9..aa3ca40d1 100644 --- a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject @@ -16,4 +16,5 @@ evaluatorSettings { "prop:" "env:" } + prettyTraces = true } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/prettyTraces.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/prettyTraces.pkl new file mode 100644 index 000000000..dbf0a1723 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/prettyTraces.pkl @@ -0,0 +1,18 @@ +amends ".../snippetTest.pkl" + +examples { + ["prettyTraces = true results in indented, multi-line trace values"] { + trace(new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + }) + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/prettyTraces.err b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/prettyTraces.err new file mode 100644 index 000000000..e326fc565 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/prettyTraces.err @@ -0,0 +1,39 @@ +examples { + ["prettyTraces = true results in indented, multi-line trace values"] { + new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } + } + } +} +pkl: TRACE: new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + } = new Dynamic { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } +} (file:///$snippetsDir/input/projects/evaluatorSettings/prettyTraces.pkl) diff --git a/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt index 687902f7c..5c8f15837 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt @@ -37,6 +37,7 @@ class AnalyzerTest { null, null, HttpClient.dummyClient(), + false, ) @Test @@ -115,6 +116,7 @@ class AnalyzerTest { tempDir.resolve("packages"), null, HttpClient.dummyClient(), + false, ) PackageServer.populateCacheDir(tempDir.resolve("packages")) val file1 = @@ -190,6 +192,7 @@ class AnalyzerTest { tempDir.resolve("packages"), project.dependencies, HttpClient.dummyClient(), + false, ) val file1 = tempDir @@ -302,6 +305,7 @@ class AnalyzerTest { tempDir.resolve("packages"), project.dependencies, HttpClient.dummyClient(), + false, ) val result = analyzer.importGraph(mainPkl.toUri()) val birdUri = URI("projectpackage://localhost:0/birds@1.0.0#/bird.pkl") diff --git a/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt index 6eef30894..f9a26185b 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt @@ -45,6 +45,7 @@ class ReplServerTest { "/".toPath(), StackFrameTransformers.defaultTransformer, false, + false, ) @Test diff --git a/pkl-core/src/test/kotlin/org/pkl/core/project/ProjectTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/project/ProjectTest.kt index b8fc92cad..b228ff61a 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/project/ProjectTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/project/ProjectTest.kt @@ -74,6 +74,7 @@ class ProjectTest { null, null, null, + null, ) val expectedAnnotations = listOf( diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java index 0e23d4460..4721093c3 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java @@ -196,7 +196,8 @@ protected CliBaseOptions getCliBaseOptions() { getHttpProxy().getOrNull(), getHttpNoProxy().getOrElse(List.of()), Map.of(), - Map.of()); + Map.of(), + false); } return cachedOptions; } diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java index 4ec124818..3f471ebef 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java @@ -164,7 +164,8 @@ protected CliBaseOptions getCliBaseOptions() { null, List.of(), Map.of(), - Map.of()); + Map.of(), + false); } return cachedOptions; } diff --git a/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt b/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt index f1cb88938..de6e3bc19 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt @@ -39,6 +39,7 @@ internal class BinaryEvaluator( moduleCacheDir: Path?, declaredDependencies: DeclaredDependencies?, outputFormat: String?, + prettyTraces: Boolean?, ) : EvaluatorImpl( transformer, @@ -54,6 +55,7 @@ internal class BinaryEvaluator( moduleCacheDir, declaredDependencies, outputFormat, + prettyTraces == true, ) { fun evaluate(moduleSource: ModuleSource, expression: String?): ByteArray { return doEvaluate(moduleSource) { module -> diff --git a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt index 7bc12f47a..482e025d4 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt @@ -225,6 +225,7 @@ class Server(private val transport: MessageTransport) : AutoCloseable { cacheDir, dependencies, message.outputFormat, + false, ) } diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt index e8bfc77f9..20a3a8dcf 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt @@ -56,6 +56,7 @@ class BinaryEvaluatorSnippetTestEngine : InputOutputTestEngine() { null, null, null, + false, ) private fun String.stripFilePaths() = diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt index fa0bbcbcb..c1167f472 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt @@ -45,6 +45,7 @@ class BinaryEvaluatorTest { null, null, null, + false, ) private fun evaluate(text: String, expression: String?) = diff --git a/stdlib/EvaluatorSettings.pkl b/stdlib/EvaluatorSettings.pkl index 539c5f8e1..8d14bb0ec 100644 --- a/stdlib/EvaluatorSettings.pkl +++ b/stdlib/EvaluatorSettings.pkl @@ -115,6 +115,10 @@ class Http { proxy: Proxy? } +/// Whether to pretty print calls to trace(), producing indented output across multiple lines. +@Since { version = "0.28.3" } +prettyTraces: Boolean? + /// Settings that control how Pkl talks to HTTP proxies. class Proxy { /// The proxy to use for HTTP(S) connections. From 4e04d9edf6e9b67309aaae705f2b026eb80abe7d Mon Sep 17 00:00:00 2001 From: Steve Salevan Date: Tue, 17 Jun 2025 15:08:21 -0400 Subject: [PATCH 2/5] Converts prettyTraces to TraceMode, loops into pkl-server --- docs/src/test/kotlin/DocSnippetTests.kt | 2 +- .../src/main/kotlin/org/pkl/cli/CliRepl.kt | 2 +- .../org/pkl/cli/repl/ReplMessagesTest.kt | 2 +- .../org/pkl/commons/cli/CliBaseOptions.kt | 5 ++- .../src/main/java/org/pkl/core/Analyzer.java | 9 +++-- .../java/org/pkl/core/EvaluatorBuilder.java | 17 ++++---- .../main/java/org/pkl/core/EvaluatorImpl.java | 5 ++- .../core/ast/expression/unary/TraceNode.java | 7 +++- .../PklEvaluatorSettings.java | 9 +++-- .../pkl/core/evaluatorSettings/TraceMode.java | 26 +++++++++++++ .../messaging/AbstractMessagePackEncoder.java | 8 ++-- .../java/org/pkl/core/project/Project.java | 11 +++--- .../java/org/pkl/core/repl/ReplServer.java | 5 ++- .../org/pkl/core/runtime/StdLibModule.java | 2 +- .../java/org/pkl/core/runtime/VmContext.java | 11 +++--- .../projects/defaultTraceMode/PklProject | 5 +++ .../defaultTraceMode/defaultTraceMode.pkl | 18 +++++++++ .../projects/evaluatorSettings/PklProject | 1 - .../evaluatorSettings/nullTraceMode.pkl | 18 +++++++++ .../input/projects/hiddenTraceMode/PklProject | 5 +++ .../hiddenTraceMode/hiddenTraceMode.pkl | 18 +++++++++ .../input/projects/prettyTraceMode/PklProject | 5 +++ .../prettyTraceMode/prettyTraceMode.pkl | 18 +++++++++ .../defaultTraceMode/defaultTraceMode.err | 28 +++++++++++++ .../evaluatorSettings/nullTraceMode.err | 28 +++++++++++++ .../hiddenTraceMode/hiddenTraceMode.pcf | 16 ++++++++ .../prettyTraceMode/prettyTraceMode.err | 39 +++++++++++++++++++ .../test/kotlin/org/pkl/core/AnalyzerTest.kt | 8 ++-- .../kotlin/org/pkl/core/ReplServerTest.kt | 2 +- .../java/org/pkl/gradle/task/BasePklTask.java | 2 +- .../java/org/pkl/gradle/task/ModulesTask.java | 2 +- .../kotlin/org/pkl/server/BinaryEvaluator.kt | 5 ++- .../src/main/kotlin/org/pkl/server/Server.kt | 2 +- .../pkl/server/ServerMessagePackDecoder.kt | 8 ++++ .../pkl/server/ServerMessagePackEncoder.kt | 4 ++ .../kotlin/org/pkl/server/ServerMessages.kt | 2 + .../org/pkl/server/AbstractServerTest.kt | 1 + .../pkl/server/BinaryEvaluatorSnippetTests.kt | 2 +- .../org/pkl/server/BinaryEvaluatorTest.kt | 2 +- .../pkl/server/ServerMessagePackCodecTest.kt | 2 + stdlib/EvaluatorSettings.pkl | 14 +++++-- 41 files changed, 320 insertions(+), 56 deletions(-) create mode 100644 pkl-core/src/main/java/org/pkl/core/evaluatorSettings/TraceMode.java create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/PklProject create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/defaultTraceMode.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/nullTraceMode.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/PklProject create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/hiddenTraceMode.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/PklProject create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/prettyTraceMode.pkl create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/projects/defaultTraceMode/defaultTraceMode.err create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/nullTraceMode.err create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/projects/hiddenTraceMode/hiddenTraceMode.pcf create mode 100644 pkl-core/src/test/files/LanguageSnippetTests/output/projects/prettyTraceMode/prettyTraceMode.err diff --git a/docs/src/test/kotlin/DocSnippetTests.kt b/docs/src/test/kotlin/DocSnippetTests.kt index 6265f49ed..c6f1cc8d3 100644 --- a/docs/src/test/kotlin/DocSnippetTests.kt +++ b/docs/src/test/kotlin/DocSnippetTests.kt @@ -97,7 +97,7 @@ class DocSnippetTestsEngine : HierarchicalTestEngine = mapOf(), - /** Whether to render calls to trace() as an indented, multi-line string. */ - val prettyTraces: Boolean = false, + /** Defines options for the formatting of calls to the trace() method. */ + val traceMode: TraceMode? = null, ) { companion object { diff --git a/pkl-core/src/main/java/org/pkl/core/Analyzer.java b/pkl-core/src/main/java/org/pkl/core/Analyzer.java index 6d5053a4a..2afc335c8 100644 --- a/pkl-core/src/main/java/org/pkl/core/Analyzer.java +++ b/pkl-core/src/main/java/org/pkl/core/Analyzer.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import org.graalvm.polyglot.Context; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.http.HttpClient; import org.pkl.core.http.HttpClientInitException; import org.pkl.core.module.ModuleKeyFactory; @@ -46,7 +47,7 @@ public class Analyzer { private final @Nullable DeclaredDependencies projectDependencies; private final ModuleResolver moduleResolver; private final HttpClient httpClient; - private final boolean prettyTraces; + private final TraceMode traceMode; public Analyzer( StackFrameTransformer transformer, @@ -56,7 +57,7 @@ public Analyzer( @Nullable Path moduleCacheDir, @Nullable DeclaredDependencies projectDependencies, HttpClient httpClient, - boolean prettyTraces) { + @Nullable TraceMode traceMode) { this.transformer = transformer; this.color = color; this.securityManager = securityManager; @@ -64,7 +65,7 @@ public Analyzer( this.projectDependencies = projectDependencies; this.moduleResolver = new ModuleResolver(moduleKeyFactories); this.httpClient = httpClient; - this.prettyTraces = prettyTraces; + this.traceMode = traceMode; } /** @@ -119,7 +120,7 @@ private Context createContext() { ? null : new ProjectDependenciesManager( projectDependencies, moduleResolver, securityManager), - prettyTraces)); + traceMode)); }); } } diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java index 97ee12258..a867642fd 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorBuilder.java @@ -21,6 +21,7 @@ import java.util.regex.Pattern; import org.pkl.core.SecurityManagers.StandardBuilder; import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.externalreader.ExternalReaderProcess; import org.pkl.core.http.HttpClient; import org.pkl.core.module.ModuleKeyFactories; @@ -67,7 +68,7 @@ public final class EvaluatorBuilder { private @Nullable DeclaredDependencies dependencies; - private boolean prettyTraces = false; + private @Nullable TraceMode traceMode; private EvaluatorBuilder() {} @@ -457,14 +458,14 @@ public EvaluatorBuilder setProjectDependencies(DeclaredDependencies dependencies } /** Sets whether calls to trace() produce indented, multi-line output. */ - public EvaluatorBuilder setPrettyTraces(boolean prettyTraces) { - this.prettyTraces = prettyTraces; + public EvaluatorBuilder setTraceMode(TraceMode traceMode) { + this.traceMode = traceMode; return this; } /** Returns whether calls to trace() produce indented, multi-line output. */ - public boolean getPrettyTraces() { - return this.prettyTraces; + public TraceMode getTraceMode() { + return this.traceMode; } /** @@ -530,7 +531,9 @@ public EvaluatorBuilder applyFromProject(Project project) { procs.computeIfAbsent(entry.getValue(), ExternalReaderProcess::of))); } } - this.prettyTraces = Boolean.TRUE.equals(settings.prettyTraces()); + if (settings.traceMode() != null) { + setTraceMode(settings.traceMode()); + } return this; } @@ -558,6 +561,6 @@ public Evaluator build() { moduleCacheDir, dependencies, outputFormat, - prettyTraces); + traceMode); } } diff --git a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java index 3d3ce3729..07f49e2f3 100644 --- a/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java +++ b/pkl-core/src/main/java/org/pkl/core/EvaluatorImpl.java @@ -30,6 +30,7 @@ import org.graalvm.polyglot.Context; import org.pkl.core.ast.ConstantValueNode; import org.pkl.core.ast.internal.ToStringNodeGen; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.http.HttpClient; import org.pkl.core.module.ModuleKeyFactory; import org.pkl.core.module.ProjectDependenciesManager; @@ -81,7 +82,7 @@ public EvaluatorImpl( @Nullable Path moduleCacheDir, @Nullable DeclaredDependencies projectDependencies, @Nullable String outputFormat, - boolean prettyTraces) { + @Nullable TraceMode traceMode) { securityManager = manager; frameTransformer = transformer; @@ -110,7 +111,7 @@ public EvaluatorImpl( ? null : new ProjectDependenciesManager( projectDependencies, moduleResolver, securityManager), - prettyTraces)); + traceMode)); }); this.timeout = timeout; // NOTE: would probably make sense to share executor between evaluators diff --git a/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java b/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java index 3fa14546f..e9c0ac3bc 100644 --- a/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java +++ b/pkl-core/src/main/java/org/pkl/core/ast/expression/unary/TraceNode.java @@ -19,6 +19,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.source.SourceSection; import org.pkl.core.ast.ExpressionNode; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.runtime.*; public final class TraceNode extends ExpressionNode { @@ -44,6 +45,10 @@ public Object executeGeneric(VirtualFrame frame) { @TruffleBoundary private void doTrace(Object value, VmContext context) { + // If traces are disabled, returns early. + if (context.getTraceMode() == TraceMode.HIDDEN) { + return; + } if (value instanceof VmObjectLike objectLike) { try { objectLike.force(true, true); @@ -53,7 +58,7 @@ private void doTrace(Object value, VmContext context) { var sourceSection = valueNode.getSourceSection(); String renderedValue; - if (context.getPrettyTraces()) { + if (context.getTraceMode() == TraceMode.PRETTY) { renderedValue = multiLineRenderer.render(value); } else { renderedValue = singleLineRenderer.render(value); diff --git a/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/PklEvaluatorSettings.java b/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/PklEvaluatorSettings.java index 95d668db2..9ebf281bc 100644 --- a/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/PklEvaluatorSettings.java +++ b/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/PklEvaluatorSettings.java @@ -49,7 +49,7 @@ public record PklEvaluatorSettings( @Nullable Http http, @Nullable Map externalModuleReaders, @Nullable Map externalResourceReaders, - @Nullable Boolean prettyTraces) { + @Nullable TraceMode traceMode) { /** Initializes a {@link PklEvaluatorSettings} from a raw object representation. */ @SuppressWarnings("unchecked") @@ -105,6 +105,7 @@ public static PklEvaluatorSettings parse( Entry::getKey, entry -> ExternalReader.parse(entry.getValue()))); var color = (String) pSettings.get("color"); + var traceMode = (String) pSettings.get("traceMode"); return new PklEvaluatorSettings( (Map) pSettings.get("externalProperties"), @@ -120,7 +121,7 @@ public static PklEvaluatorSettings parse( Http.parse((Value) pSettings.get("http")), externalModuleReaders, externalResourceReaders, - (Boolean) pSettings.get("prettyTraces")); + traceMode == null ? null : TraceMode.valueOf(traceMode.toUpperCase())); } public record Http(@Nullable Proxy proxy) { @@ -216,7 +217,7 @@ && arePatternsEqual(allowedResources, that.allowedResources) && Objects.equals(timeout, that.timeout) && Objects.equals(rootDir, that.rootDir) && Objects.equals(http, that.http) - && Objects.equals(prettyTraces, that.prettyTraces); + && Objects.equals(traceMode, that.traceMode); } private int hashPatterns(@Nullable List patterns) { @@ -242,7 +243,7 @@ public int hashCode() { timeout, rootDir, http, - prettyTraces); + traceMode); result = 31 * result + hashPatterns(allowedModules); result = 31 * result + hashPatterns(allowedResources); return result; diff --git a/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/TraceMode.java b/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/TraceMode.java new file mode 100644 index 000000000..a984eb3d2 --- /dev/null +++ b/pkl-core/src/main/java/org/pkl/core/evaluatorSettings/TraceMode.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2025 Apple Inc. and the Pkl project 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 + * + * https://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. + */ +package org.pkl.core.evaluatorSettings; + +/** Dictates the rendering of calls to the trace() method within Pkl. */ +public enum TraceMode { + /** All trace() calls will not be emitted to stderr. */ + HIDDEN, + /** All structures passed to trace() will be emitted on a single line. */ + DEFAULT, + /** All structures passed to trace() will be indented and emitted across multiple lines. */ + PRETTY +} diff --git a/pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackEncoder.java b/pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackEncoder.java index 841ff50ba..33ab16d1c 100644 --- a/pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackEncoder.java +++ b/pkl-core/src/main/java/org/pkl/core/messaging/AbstractMessagePackEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. + * Copyright © 2024-2025 Apple Inc. and the Pkl project 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. @@ -72,7 +72,8 @@ protected void packMapHeader( @Nullable Object valueC, @Nullable Object valueD, @Nullable Object valueE, - @Nullable Object valueF) + @Nullable Object valueF, + @Nullable Object valueG) throws IOException { packer.packMapHeader( size @@ -90,7 +91,8 @@ protected void packMapHeader( + (valueC != null ? 1 : 0) + (valueD != null ? 1 : 0) + (valueE != null ? 1 : 0) - + (valueF != null ? 1 : 0)); + + (valueF != null ? 1 : 0) + + (valueG != null ? 1 : 0)); } protected void packKeyValue(String name, @Nullable Integer value) throws IOException { diff --git a/pkl-core/src/main/java/org/pkl/core/project/Project.java b/pkl-core/src/main/java/org/pkl/core/project/Project.java index f3434dc9c..5757b4398 100644 --- a/pkl-core/src/main/java/org/pkl/core/project/Project.java +++ b/pkl-core/src/main/java/org/pkl/core/project/Project.java @@ -43,6 +43,7 @@ import org.pkl.core.Value; import org.pkl.core.Version; import org.pkl.core.evaluatorSettings.PklEvaluatorSettings; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.module.ModuleKeyFactories; import org.pkl.core.packages.Checksums; import org.pkl.core.packages.Dependency.RemoteDependency; @@ -198,7 +199,7 @@ private static List> findImportCycle(ModuleSource moduleSource) { builder.getModuleCacheDir(), builder.getProjectDependencies(), builder.getHttpClient(), - builder.getPrettyTraces()); + builder.getTraceMode()); var importGraph = analyzer.importGraph(moduleSource.getUri()); var ret = ImportGraphUtils.findImportCycles(importGraph); // we only care about cycles in the same scheme as `moduleSource` @@ -513,7 +514,7 @@ public EvaluatorSettings( @Nullable List modulePath, @Nullable Duration timeout, @Nullable Path rootDir, - @Nullable Boolean prettyTraces) { + @Nullable TraceMode traceMode) { this.delegate = new PklEvaluatorSettings( externalProperties, @@ -529,7 +530,7 @@ public EvaluatorSettings( null, null, null, - prettyTraces); + traceMode); } @Deprecated(forRemoval = true) @@ -613,8 +614,8 @@ public String toString() { + delegate.timeout() + ", rootDir=" + delegate.rootDir() - + ", prettyTraces=" - + delegate.prettyTraces() + + ", traceMode=" + + delegate.traceMode() + '}'; } } diff --git a/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java b/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java index 11a847f88..738f2c93b 100644 --- a/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java +++ b/pkl-core/src/main/java/org/pkl/core/repl/ReplServer.java @@ -32,6 +32,7 @@ import org.pkl.core.ast.member.*; import org.pkl.core.ast.repl.ResolveClassMemberNode; import org.pkl.core.ast.type.TypeNode; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.http.HttpClient; import org.pkl.core.module.*; import org.pkl.core.packages.PackageResolver; @@ -83,7 +84,7 @@ public ReplServer( Path workingDir, StackFrameTransformer frameTransformer, boolean color, - boolean prettyTraces) { + @Nullable TraceMode traceMode) { this.workingDir = workingDir; this.securityManager = securityManager; @@ -116,7 +117,7 @@ public ReplServer( outputFormat, packageResolver, projectDependenciesManager, - prettyTraces)); + traceMode)); }); language = languageRef.get(); } diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java b/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java index f53f57458..d0e8b8b95 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/StdLibModule.java @@ -50,7 +50,7 @@ protected static void loadModule(URI uri, VmTyped instance) { null, null, null, - false)); + null)); var language = VmLanguage.get(null); var moduleKey = ModuleKeys.standardLibrary(uri); var source = VmUtils.loadSource((ResolvedModuleKey) moduleKey); diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java b/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java index 75bb9dedc..c80837d38 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/VmContext.java @@ -23,6 +23,7 @@ import org.pkl.core.Logger; import org.pkl.core.SecurityManager; import org.pkl.core.StackFrameTransformer; +import org.pkl.core.evaluatorSettings.TraceMode; import org.pkl.core.http.HttpClient; import org.pkl.core.module.ProjectDependenciesManager; import org.pkl.core.packages.PackageResolver; @@ -50,7 +51,7 @@ public static final class Holder { private final ModuleCache moduleCache; private final @Nullable PackageResolver packageResolver; private final @Nullable ProjectDependenciesManager projectDependenciesManager; - private final boolean prettyTraces; + private final TraceMode traceMode; public Holder( StackFrameTransformer frameTransformer, @@ -65,7 +66,7 @@ public Holder( @Nullable String outputFormat, @Nullable PackageResolver packageResolver, @Nullable ProjectDependenciesManager projectDependenciesManager, - boolean prettyTraces) { + @Nullable TraceMode traceMode) { this.frameTransformer = frameTransformer; this.securityManager = securityManager; @@ -86,7 +87,7 @@ public Holder( moduleCache = new ModuleCache(); this.packageResolver = packageResolver; this.projectDependenciesManager = projectDependenciesManager; - this.prettyTraces = prettyTraces; + this.traceMode = traceMode; } } @@ -147,7 +148,7 @@ public Map getExternalProperties() { return holder.projectDependenciesManager; } - public boolean getPrettyTraces() { - return holder.prettyTraces; + public @Nullable TraceMode getTraceMode() { + return holder.traceMode; } } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/PklProject b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/PklProject new file mode 100644 index 000000000..b2cc53e6d --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/PklProject @@ -0,0 +1,5 @@ +amends "pkl:Project" + +evaluatorSettings { + traceMode = "default" +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/defaultTraceMode.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/defaultTraceMode.pkl new file mode 100644 index 000000000..1088350a9 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/defaultTraceMode/defaultTraceMode.pkl @@ -0,0 +1,18 @@ +amends ".../snippetTest.pkl" + +examples { + ["traceMode = 'default' results in single-line trace() values"] { + trace(new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + }) + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject index aa3ca40d1..1040058e9 100644 --- a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/PklProject @@ -16,5 +16,4 @@ evaluatorSettings { "prop:" "env:" } - prettyTraces = true } diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/nullTraceMode.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/nullTraceMode.pkl new file mode 100644 index 000000000..8e4b8693b --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/evaluatorSettings/nullTraceMode.pkl @@ -0,0 +1,18 @@ +amends ".../snippetTest.pkl" + +examples { + ["traceMode = null results in single-line trace() values"] { + trace(new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + }) + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/PklProject b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/PklProject new file mode 100644 index 000000000..687d256a2 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/PklProject @@ -0,0 +1,5 @@ +amends "pkl:Project" + +evaluatorSettings { + traceMode = "hidden" +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/hiddenTraceMode.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/hiddenTraceMode.pkl new file mode 100644 index 000000000..813655b69 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/hiddenTraceMode/hiddenTraceMode.pkl @@ -0,0 +1,18 @@ +amends ".../snippetTest.pkl" + +examples { + ["traceMode = 'hidden' results in no trace output"] { + trace(new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + }) + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/PklProject b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/PklProject new file mode 100644 index 000000000..30bf1bcd7 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/PklProject @@ -0,0 +1,5 @@ +amends "pkl:Project" + +evaluatorSettings { + traceMode = "pretty" +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/prettyTraceMode.pkl b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/prettyTraceMode.pkl new file mode 100644 index 000000000..15523cdfb --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/input/projects/prettyTraceMode/prettyTraceMode.pkl @@ -0,0 +1,18 @@ +amends ".../snippetTest.pkl" + +examples { + ["traceMode = 'pretty' results in indented, multi-line output"] { + trace(new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + }) + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/projects/defaultTraceMode/defaultTraceMode.err b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/defaultTraceMode/defaultTraceMode.err new file mode 100644 index 000000000..f6f17aaa0 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/defaultTraceMode/defaultTraceMode.err @@ -0,0 +1,28 @@ +examples { + ["traceMode = 'default' results in single-line trace() values"] { + new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } + } + } +} +pkl: TRACE: new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + } = new Dynamic { ["Parrot"] { name = "Parrot"; age = 1234; bucketSettings { kicked = true; ["fjordConfig"] { isPining = true } } } } (file:///$snippetsDir/input/projects/defaultTraceMode/defaultTraceMode.pkl) diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/nullTraceMode.err b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/nullTraceMode.err new file mode 100644 index 000000000..1c5bddea2 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/evaluatorSettings/nullTraceMode.err @@ -0,0 +1,28 @@ +examples { + ["traceMode = null results in single-line trace() values"] { + new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } + } + } +} +pkl: TRACE: new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + } = new Dynamic { ["Parrot"] { name = "Parrot"; age = 1234; bucketSettings { kicked = true; ["fjordConfig"] { isPining = true } } } } (file:///$snippetsDir/input/projects/evaluatorSettings/nullTraceMode.pkl) diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/projects/hiddenTraceMode/hiddenTraceMode.pcf b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/hiddenTraceMode/hiddenTraceMode.pcf new file mode 100644 index 000000000..04d2056a6 --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/hiddenTraceMode/hiddenTraceMode.pcf @@ -0,0 +1,16 @@ +examples { + ["traceMode = 'hidden' results in no trace output"] { + new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } + } + } +} diff --git a/pkl-core/src/test/files/LanguageSnippetTests/output/projects/prettyTraceMode/prettyTraceMode.err b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/prettyTraceMode/prettyTraceMode.err new file mode 100644 index 000000000..8d709286c --- /dev/null +++ b/pkl-core/src/test/files/LanguageSnippetTests/output/projects/prettyTraceMode/prettyTraceMode.err @@ -0,0 +1,39 @@ +examples { + ["traceMode = 'pretty' results in indented, multi-line output"] { + new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } + } + } +} +pkl: TRACE: new { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings = new { + kicked = true + ["fjordConfig"] = new { + isPining = true + } + } + } + } = new Dynamic { + ["Parrot"] { + name = "Parrot" + age = 1234 + bucketSettings { + kicked = true + ["fjordConfig"] { + isPining = true + } + } + } +} (file:///$snippetsDir/input/projects/prettyTraceMode/prettyTraceMode.pkl) diff --git a/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt index 5c8f15837..caa2391ba 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/AnalyzerTest.kt @@ -37,7 +37,7 @@ class AnalyzerTest { null, null, HttpClient.dummyClient(), - false, + null, ) @Test @@ -116,7 +116,7 @@ class AnalyzerTest { tempDir.resolve("packages"), null, HttpClient.dummyClient(), - false, + null, ) PackageServer.populateCacheDir(tempDir.resolve("packages")) val file1 = @@ -192,7 +192,7 @@ class AnalyzerTest { tempDir.resolve("packages"), project.dependencies, HttpClient.dummyClient(), - false, + null, ) val file1 = tempDir @@ -305,7 +305,7 @@ class AnalyzerTest { tempDir.resolve("packages"), project.dependencies, HttpClient.dummyClient(), - false, + null, ) val result = analyzer.importGraph(mainPkl.toUri()) val birdUri = URI("projectpackage://localhost:0/birds@1.0.0#/bird.pkl") diff --git a/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt index f9a26185b..37b80c647 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/ReplServerTest.kt @@ -45,7 +45,7 @@ class ReplServerTest { "/".toPath(), StackFrameTransformers.defaultTransformer, false, - false, + null, ) @Test diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java index 4721093c3..30571fd13 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/BasePklTask.java @@ -197,7 +197,7 @@ protected CliBaseOptions getCliBaseOptions() { getHttpNoProxy().getOrElse(List.of()), Map.of(), Map.of(), - false); + null); } return cachedOptions; } diff --git a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java index 3f471ebef..f54f36bd0 100644 --- a/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java +++ b/pkl-gradle/src/main/java/org/pkl/gradle/task/ModulesTask.java @@ -165,7 +165,7 @@ protected CliBaseOptions getCliBaseOptions() { List.of(), Map.of(), Map.of(), - false); + null); } return cachedOptions; } diff --git a/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt b/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt index de6e3bc19..b509aaaec 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/BinaryEvaluator.kt @@ -20,6 +20,7 @@ import java.time.Duration import org.msgpack.core.MessagePacker import org.pkl.core.* import org.pkl.core.ast.member.ObjectMember +import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.http.HttpClient import org.pkl.core.module.ModuleKeyFactory import org.pkl.core.project.DeclaredDependencies @@ -39,7 +40,7 @@ internal class BinaryEvaluator( moduleCacheDir: Path?, declaredDependencies: DeclaredDependencies?, outputFormat: String?, - prettyTraces: Boolean?, + traceMode: TraceMode?, ) : EvaluatorImpl( transformer, @@ -55,7 +56,7 @@ internal class BinaryEvaluator( moduleCacheDir, declaredDependencies, outputFormat, - prettyTraces == true, + traceMode, ) { fun evaluate(moduleSource: ModuleSource, expression: String?): ByteArray { return doEvaluate(moduleSource) { module -> diff --git a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt index 482e025d4..99040806e 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/Server.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/Server.kt @@ -225,7 +225,7 @@ class Server(private val transport: MessageTransport) : AutoCloseable { cacheDir, dependencies, message.outputFormat, - false, + message.traceMode, ) } diff --git a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackDecoder.kt b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackDecoder.kt index 62926a727..b4b846830 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackDecoder.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackDecoder.kt @@ -22,6 +22,7 @@ import java.time.Duration import org.msgpack.core.MessagePack import org.msgpack.core.MessageUnpacker import org.msgpack.value.Value +import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.messaging.BaseMessagePackDecoder import org.pkl.core.messaging.Message import org.pkl.core.packages.Checksums @@ -50,6 +51,13 @@ class ServerMessagePackDecoder(unpacker: MessageUnpacker) : BaseMessagePackDecod map.unpackHttp(), unpackStringMapOrNull(map, "externalModuleReaders", ::unpackExternalReader), unpackStringMapOrNull(map, "externalResourceReaders", ::unpackExternalReader), + unpackStringOrNull( + map, + "traceMode", + fun(traceMode: String): TraceMode { + return TraceMode.valueOf(traceMode.uppercase()) + }, + ), ) Message.Type.CREATE_EVALUATOR_RESPONSE -> CreateEvaluatorResponse( diff --git a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackEncoder.kt b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackEncoder.kt index b613cd3f0..28e4b9e86 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackEncoder.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessagePackEncoder.kt @@ -102,6 +102,7 @@ class ServerMessagePackEncoder(packer: MessagePacker) : BaseMessagePackEncoder(p msg.http, msg.externalModuleReaders, msg.externalResourceReaders, + msg.traceMode, ) packKeyValue("requestId", msg.requestId()) packKeyValue("allowedModules", msg.allowedModules) @@ -151,6 +152,9 @@ class ServerMessagePackEncoder(packer: MessagePacker) : BaseMessagePackEncoder(p packExternalReader(spec) } } + if (msg.traceMode != null) { + packKeyValue("traceMode", msg.traceMode.toString()) + } return } Message.Type.CREATE_EVALUATOR_RESPONSE -> { diff --git a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessages.kt b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessages.kt index 5eb3fe645..ef417a557 100644 --- a/pkl-server/src/main/kotlin/org/pkl/server/ServerMessages.kt +++ b/pkl-server/src/main/kotlin/org/pkl/server/ServerMessages.kt @@ -19,6 +19,7 @@ import java.net.URI import java.nio.file.Path import java.time.Duration import java.util.* +import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.messaging.Message import org.pkl.core.messaging.Messages import org.pkl.core.packages.Checksums @@ -40,6 +41,7 @@ data class CreateEvaluatorRequest( val http: Http?, val externalModuleReaders: Map?, val externalResourceReaders: Map?, + val traceMode: TraceMode?, ) : Message.Client.Request { override fun type(): Message.Type = Message.Type.CREATE_EVALUATOR_REQUEST diff --git a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt index 6d644d9b1..b0646615b 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/AbstractServerTest.kt @@ -961,6 +961,7 @@ abstract class AbstractServerTest { http, null, null, + null, ) send(message) diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt index 20a3a8dcf..f374a3b57 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorSnippetTests.kt @@ -56,7 +56,7 @@ class BinaryEvaluatorSnippetTestEngine : InputOutputTestEngine() { null, null, null, - false, + null, ) private fun String.stripFilePaths() = diff --git a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt index c1167f472..9c38c8885 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/BinaryEvaluatorTest.kt @@ -45,7 +45,7 @@ class BinaryEvaluatorTest { null, null, null, - false, + null, ) private fun evaluate(text: String, expression: String?) = diff --git a/pkl-server/src/test/kotlin/org/pkl/server/ServerMessagePackCodecTest.kt b/pkl-server/src/test/kotlin/org/pkl/server/ServerMessagePackCodecTest.kt index 8ecfd0cf9..35b991012 100644 --- a/pkl-server/src/test/kotlin/org/pkl/server/ServerMessagePackCodecTest.kt +++ b/pkl-server/src/test/kotlin/org/pkl/server/ServerMessagePackCodecTest.kt @@ -23,6 +23,7 @@ import java.time.Duration import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.msgpack.core.MessagePack +import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.messaging.Message import org.pkl.core.messaging.MessageDecoder import org.pkl.core.messaging.MessageEncoder @@ -99,6 +100,7 @@ class ServerMessagePackCodecTest { ), externalModuleReaders = mapOf("external" to externalReader, "external2" to externalReader), externalResourceReaders = mapOf("external" to externalReader), + traceMode = TraceMode.PRETTY, ) ) } diff --git a/stdlib/EvaluatorSettings.pkl b/stdlib/EvaluatorSettings.pkl index 8d14bb0ec..cc1eb2cb7 100644 --- a/stdlib/EvaluatorSettings.pkl +++ b/stdlib/EvaluatorSettings.pkl @@ -109,16 +109,22 @@ externalModuleReaders: Mapping? @Since { version = "0.27.0" } externalResourceReaders: Mapping? +/// Defines options for the formatting of calls to the trace() method. +/// +/// Possible values: +/// +/// - `"hidden"`: All trace() calls will not be emitted to stderr. +/// - `"default"`: All structures passed to trace() will be emitted on a single line. +/// - `"pretty"`: All structures passed to trace() will be indented and emitted across multiple lines. +@Since { version = "0.29.0" } +traceMode: ("hidden"|"default"|"pretty")? + /// Settings that control how Pkl talks to HTTP(S) servers. class Http { /// Configuration of the HTTP proxy to use. proxy: Proxy? } -/// Whether to pretty print calls to trace(), producing indented output across multiple lines. -@Since { version = "0.28.3" } -prettyTraces: Boolean? - /// Settings that control how Pkl talks to HTTP proxies. class Proxy { /// The proxy to use for HTTP(S) connections. From 9e1a00128d4cb63fc2d7206610789f8c2a3e04c2 Mon Sep 17 00:00:00 2001 From: Steve Salevan Date: Tue, 17 Jun 2025 15:17:23 -0400 Subject: [PATCH 3/5] Adds traceMode option to CLI arguments --- .../org/pkl/commons/cli/commands/BaseOptions.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/commands/BaseOptions.kt b/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/commands/BaseOptions.kt index a82416f42..ef4020e8a 100644 --- a/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/commands/BaseOptions.kt +++ b/pkl-commons-cli/src/main/kotlin/org/pkl/commons/cli/commands/BaseOptions.kt @@ -32,6 +32,7 @@ import org.pkl.commons.cli.CliException import org.pkl.commons.shlex import org.pkl.core.evaluatorSettings.Color import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader +import org.pkl.core.evaluatorSettings.TraceMode import org.pkl.core.runtime.VmUtils import org.pkl.core.util.IoUtils @@ -255,6 +256,17 @@ class BaseOptions : OptionGroup() { .multiple() .toMap() + val traceMode: TraceMode by + option( + names = arrayOf("--trace-mode"), + metavar = "when", + help = + "Specifies how calls to trace() are formatted. Possible values of are 'default', 'pretty' and 'hidden'.", + ) + .enum { it.name.lowercase() } + .single() + .default(TraceMode.DEFAULT) + // hidden option used by native tests private val testPort: Int by option(names = arrayOf("--test-port"), help = "Internal test option", hidden = true) @@ -291,6 +303,7 @@ class BaseOptions : OptionGroup() { httpNoProxy = noProxy ?: emptyList(), externalModuleReaders = externalModuleReaders, externalResourceReaders = externalResourceReaders, + traceMode = traceMode, ) } } From 7811c156e6172ab6f7bfccedf5742c819edae821 Mon Sep 17 00:00:00 2001 From: Steve Salevan Date: Tue, 17 Jun 2025 15:20:45 -0400 Subject: [PATCH 4/5] Correct missing TraceMode specification --- bench/src/jmh/java/org/pkl/core/ListSort.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/src/jmh/java/org/pkl/core/ListSort.java b/bench/src/jmh/java/org/pkl/core/ListSort.java index c3b2accca..3a2a32e3b 100644 --- a/bench/src/jmh/java/org/pkl/core/ListSort.java +++ b/bench/src/jmh/java/org/pkl/core/ListSort.java @@ -52,7 +52,7 @@ public class ListSort { IoUtils.getCurrentWorkingDir(), StackFrameTransformers.defaultTransformer, false, - false); + null); private static final List list = new ArrayList<>(100000); static { From f72b1f1e84441fcbeb718326f9850ee566197649 Mon Sep 17 00:00:00 2001 From: Steve Salevan Date: Wed, 18 Jun 2025 11:45:27 -0400 Subject: [PATCH 5/5] Bumps version to 0.30.0 --- stdlib/EvaluatorSettings.pkl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/EvaluatorSettings.pkl b/stdlib/EvaluatorSettings.pkl index cc1eb2cb7..5cd86335d 100644 --- a/stdlib/EvaluatorSettings.pkl +++ b/stdlib/EvaluatorSettings.pkl @@ -116,7 +116,7 @@ externalResourceReaders: Mapping? /// - `"hidden"`: All trace() calls will not be emitted to stderr. /// - `"default"`: All structures passed to trace() will be emitted on a single line. /// - `"pretty"`: All structures passed to trace() will be indented and emitted across multiple lines. -@Since { version = "0.29.0" } +@Since { version = "0.30.0" } traceMode: ("hidden"|"default"|"pretty")? /// Settings that control how Pkl talks to HTTP(S) servers.