Require global settings file to use pkl:settings (#477)

This is technically a breaking change, but follows the intended use-case
and documentation of settings.

* Require that the global settings file at `~/.pkl/settings.pkl`
amends stdlib module `pkl:settings`, or otherwise sets `output.value`
to an instance of `pkl.Settings`.
* Simplify the object mapping of `PklSettings.java`
This commit is contained in:
Daniel Chao
2024-05-07 07:49:00 -07:00
committed by GitHub
parent aeb17588b3
commit 21aa44cfc4
5 changed files with 19 additions and 19 deletions

View File

@@ -37,6 +37,7 @@ public final class PClassInfo<T> implements Serializable {
public static final URI pklBaseUri = URI.create("pkl:base"); public static final URI pklBaseUri = URI.create("pkl:base");
public static final URI pklSemverUri = URI.create("pkl:semver"); public static final URI pklSemverUri = URI.create("pkl:semver");
public static final URI pklSettingsUri = URI.create("pkl:settings");
public static final URI pklProjectUri = URI.create("pkl:Project"); public static final URI pklProjectUri = URI.create("pkl:Project");
public static final PClassInfo<Void> Any = pklBaseClassInfo("Any", Void.class); public static final PClassInfo<Void> Any = pklBaseClassInfo("Any", Void.class);
@@ -79,6 +80,8 @@ public final class PClassInfo<T> implements Serializable {
new PClassInfo<>("pkl.semver", "Version", PObject.class, pklSemverUri); new PClassInfo<>("pkl.semver", "Version", PObject.class, pklSemverUri);
public static final PClassInfo<PObject> Project = public static final PClassInfo<PObject> Project =
new PClassInfo<>("pkl.Project", "ModuleClass", PObject.class, pklProjectUri); new PClassInfo<>("pkl.Project", "ModuleClass", PObject.class, pklProjectUri);
public static final PClassInfo<PObject> Settings =
new PClassInfo<>("pkl.settings", "ModuleClass", PObject.class, pklSettingsUri);
public static final PClassInfo<Object> Unavailable = public static final PClassInfo<Object> Unavailable =
new PClassInfo<>("unavailable", "unavailable", Object.class, URI.create("pkl:unavailable")); new PClassInfo<>("unavailable", "unavailable", Object.class, URI.create("pkl:unavailable"));

View File

@@ -15,13 +15,13 @@
*/ */
package org.pkl.core.runtime; package org.pkl.core.runtime;
import java.net.URI; import static org.pkl.core.PClassInfo.pklSettingsUri;
public final class SettingsModule extends StdLibModule { public final class SettingsModule extends StdLibModule {
private static final VmTyped instance = VmUtils.createEmptyModule(); private static final VmTyped instance = VmUtils.createEmptyModule();
static { static {
loadModule(URI.create("pkl:settings"), instance); loadModule(pklSettingsUri, instance);
} }
private SettingsModule() {} private SettingsModule() {}

View File

@@ -23,7 +23,6 @@ import org.pkl.core.*;
import org.pkl.core.module.ModuleKeyFactories; import org.pkl.core.module.ModuleKeyFactories;
import org.pkl.core.resource.ResourceReaders; import org.pkl.core.resource.ResourceReaders;
import org.pkl.core.runtime.VmEvalException; import org.pkl.core.runtime.VmEvalException;
import org.pkl.core.runtime.VmExceptionBuilder;
import org.pkl.core.util.IoUtils; import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable; import org.pkl.core.util.Nullable;
@@ -73,23 +72,16 @@ public final class PklSettings {
.addResourceReader(ResourceReaders.environmentVariable()) .addResourceReader(ResourceReaders.environmentVariable())
.addEnvironmentVariables(System.getenv()) .addEnvironmentVariables(System.getenv())
.build()) { .build()) {
var module = evaluator.evaluate(moduleSource); var module = evaluator.evaluateOutputValueAs(moduleSource, PClassInfo.Settings);
return parseSettings(module, moduleSource); return parseSettings(module);
} }
} }
private static PklSettings parseSettings(PModule module, ModuleSource location) private static PklSettings parseSettings(PObject module) throws VmEvalException {
throws VmEvalException {
// can't use object mapping in pkl-core, so map manually // can't use object mapping in pkl-core, so map manually
var editor = module.getPropertyOrNull("editor"); var editor = (PObject) module.getProperty("editor");
if (!(editor instanceof PObject pObject)) { var urlScheme = (String) editor.getProperty("urlScheme");
throw new VmExceptionBuilder().evalError("invalidSettingsFile", location.getUri()).build(); return new PklSettings(new Editor(urlScheme));
}
var urlScheme = pObject.getPropertyOrNull("urlScheme");
if (!(urlScheme instanceof String string)) {
throw new VmExceptionBuilder().evalError("invalidSettingsFile", location.getUri()).build();
}
return new PklSettings(new Editor(string));
} }
/** Returns the editor for viewing and editing Pkl files. */ /** Returns the editor for viewing and editing Pkl files. */

View File

@@ -700,9 +700,6 @@ Refusing to load module `{0}` because it does not match any entry in the module
insufficientModuleTrustLevel=\ insufficientModuleTrustLevel=\
Refusing to import module `{0}` because importing module `{1}` has an insufficient trust level. Refusing to import module `{0}` because importing module `{1}` has an insufficient trust level.
invalidSettingsFile=\
Pkl settings file `{0}` must start with `amends "pkl:settings"`.
invalidRegexSyntax=\ invalidRegexSyntax=\
Syntax error in regex `{0}`: {1} Syntax error in regex `{0}`: {1}

View File

@@ -2,6 +2,7 @@ package org.pkl.core.settings
import java.nio.file.Path import java.nio.file.Path
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatCode
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir import org.junit.jupiter.api.io.TempDir
import org.pkl.commons.createParentDirectories import org.pkl.commons.createParentDirectories
@@ -67,6 +68,13 @@ class PklSettingsTest {
checkEquals(Editor.VS_CODE, module.getProperty("vsCode") as PObject) checkEquals(Editor.VS_CODE, module.getProperty("vsCode") as PObject)
} }
@Test
fun `invalid settings file`(@TempDir tempDir: Path) {
val settingsFile = tempDir.resolve("settings.pkl").apply { writeString("foo = 1") }
assertThatCode { PklSettings.loadFromPklHomeDir(tempDir) }
.hasMessageContaining("Expected `output.value` of module `${settingsFile.toUri()}` to be of type `pkl.settings`, but got type `settings`.")
}
private fun checkEquals(expected: Editor, actual: PObject) { private fun checkEquals(expected: Editor, actual: PObject) {
assertThat(actual.getProperty("urlScheme") as String).isEqualTo(expected.urlScheme) assertThat(actual.getProperty("urlScheme") as String).isEqualTo(expected.urlScheme)
} }