diff --git a/modules/kernels/bash/default.nix b/modules/kernels/bash/default.nix index acb45ae..60ac8d1 100644 --- a/modules/kernels/bash/default.nix +++ b/modules/kernels/bash/default.nix @@ -12,7 +12,7 @@ , settingsSchema }: -with { inherit (settings) attrs extensions; }; +with { inherit (settings.interface) attrs extensions; }; let kernelName = "bash"; diff --git a/modules/kernels/bash/module.nix b/modules/kernels/bash/module.nix index 7f92849..ad05670 100644 --- a/modules/kernels/bash/module.nix +++ b/modules/kernels/bash/module.nix @@ -1,4 +1,4 @@ -{ config, options, lib, pkgs, nixosOptionsToSettingsSchema, ... }: +{ config, options, lib, pkgs, nixosOptionsToSettingsSchema, boilerplate, ... }: with lib; @@ -12,12 +12,15 @@ with lib; visible = false; }; - attrs = mkOption { + interface.attrs = mkOption { + example = boilerplate.attrsTitle; + description = boilerplate.attrsDescription; type = types.listOf types.str; default = ["bash"]; }; - - extensions = mkOption { + interface.extensions = mkOption { + example = boilerplate.extensionsTitle; + description = boilerplate.extensionsDescription; type = types.listOf types.str; default = ["sh" "bash"]; }; diff --git a/modules/kernels/python/module.nix b/modules/kernels/python/module.nix index f731c2c..e044770 100644 --- a/modules/kernels/python/module.nix +++ b/modules/kernels/python/module.nix @@ -1,4 +1,4 @@ -{ config, options, lib, pkgs, nixosOptionsToSettingsSchema, ... }: +{ config, options, lib, pkgs, nixosOptionsToSettingsSchema, boilerplate, ... }: with lib; @@ -20,14 +20,14 @@ let python3Package = packageOption; interface.attrs = mkOption { - example = "Notebook attributes"; - description = "Notebook cells that have these attributes will match this kernel, allowing it to run the code."; + example = boilerplate.attrsTitle; + description = boilerplate.attrsDescription; type = types.listOf types.str; default = ["python"]; }; interface.extensions = mkOption { - example = "File extensions"; - description = "Files with these extensions will match against this kernel, allowing you to run the code as if it were a Jupyter cell."; + example = boilerplate.extensionsTitle; + description = boilerplate.extensionsDescription; type = types.listOf types.str; default = ["py"]; }; diff --git a/nix/evaluate-config.nix b/nix/evaluate-config.nix index b761ef7..89eefe3 100644 --- a/nix/evaluate-config.nix +++ b/nix/evaluate-config.nix @@ -8,6 +8,13 @@ config: lib.evalModules { specialArgs = { nixosOptionsToSettingsSchema = pkgsStable.callPackage ../modules/base/nixos-options-to-settings-schema.nix {}; + boilerplate = { + attrsTitle = "Notebook attributes"; + attrsDescription = "Notebook cells that have these attributes will match this kernel, allowing it to run the code."; + + extensionsTitle = "File extensions"; + extensionsDescription = "Files with these extensions will match against this kernel, allowing you to run the code as if it were a Jupyter cell."; + }; }; modules = [ ../modules/base.nix diff --git a/tests/app/Spec/Tests/SettingsSchemas.hs b/tests/app/Spec/Tests/SettingsSchemas.hs new file mode 100644 index 0000000..a631180 --- /dev/null +++ b/tests/app/Spec/Tests/SettingsSchemas.hs @@ -0,0 +1,49 @@ +{-# OPTIONS_GHC -fno-warn-unused-top-binds #-} + +module Spec.Tests.SettingsSchemas (tests) where + +import Control.Monad.IO.Class +import Data.Aeson as A +import qualified Data.Map as M +import Data.Maybe +import Data.String.Interpolate +import Data.Text +import Test.Sandwich as Sandwich +import TestLib.JupyterRunnerContext +import TestLib.TestBuilding +import TestLib.Types +import TestLib.Util + + +type PackageName = Text +type TargetName = Text +type AllSettingsSchemas = M.Map PackageName (M.Map TargetName A.Object) + +tests :: SimpleSpec +tests = describe "Settings schemas" $ do + it "all settings schema items have required fields" $ do + allSettingsSchemasFile <- testBuildUsingFlake ".#allSettingsSchemas" + info [i|Got file: #{allSettingsSchemasFile}|] + + Right (byPackage :: AllSettingsSchemas) <- liftIO $ A.eitherDecodeFileStrict allSettingsSchemasFile + + itemsLackingField byPackage "defaultValue" `shouldBe` [] + + info [i|Num lacking title: #{Prelude.length (itemsLackingField byPackage "title")}|] + itemsLackingField byPackage "title" `shouldBe` [] + +itemsLackingField :: AllSettingsSchemas -> Text -> [Text] +itemsLackingField byPackage field = catMaybes [ + classify packageName targetName item + | (packageName, m) <- M.toList byPackage + , (targetName, item) <- M.toList m + ] + where + classify packageName targetName item = case item of + (aesonLookup field -> Just _) -> Nothing + _ -> Just ([i|#{packageName}.#{targetName}|] :: Text) + +main :: IO () +main = runSandwichWithCommandLineArgs Sandwich.defaultOptions $ + introduceBootstrapNixpkgs $ + tests diff --git a/tests/src/TestLib/TestBuilding.hs b/tests/src/TestLib/TestBuilding.hs index d78e01a..952efbe 100644 --- a/tests/src/TestLib/TestBuilding.hs +++ b/tests/src/TestLib/TestBuilding.hs @@ -5,12 +5,17 @@ module TestLib.TestBuilding where import Conduit as C import Control.Monad.Logger import Control.Monad.Reader +import Data.Aeson as A +import Data.ByteString.Lazy.Char8 as BL8 import Data.Function import qualified Data.List as L +import Data.String.Interpolate +import Data.Text as T import GHC.Stack import System.Exit import System.FilePath import Test.Sandwich +import TestLib.JupyterRunnerContext import TestLib.Types import TestLib.Util import UnliftIO.Directory @@ -21,22 +26,37 @@ import UnliftIO.Process testBuild :: ( HasCallStack, MonadUnliftIO m, MonadLogger m, MonadReader context m , HasBaseContext context, HasBootstrapNixpkgs context - ) => String -> m () + ) => String -> m FilePath testBuild = testBuild' LevelDebug testBuild' :: ( HasCallStack, MonadUnliftIO m, MonadLogger m, MonadReader context m , HasBaseContext context, HasBootstrapNixpkgs context - ) => LogLevel -> String -> m () + ) => LogLevel -> String -> m FilePath testBuild' logLevel expr = do rootDir <- findFirstParentMatching (\x -> doesPathExist (x ".git")) env <- getEnvWithNixPath + let cp = (proc "nix-build" [".", "-A", expr, "--no-out-link"]) { + cwd = Just rootDir + , env = Just env + } + (T.unpack . T.strip . T.pack) <$> (readCreateProcessWithLogging' logLevel cp "") - p <- createProcessWithLogging' logLevel $ (proc "nix-build" [".", "-A", expr, "--no-out-link"]) { - cwd = Just rootDir - , env = Just env - } - waitForProcess p >>= (`shouldBe` ExitSuccess) +testBuildUsingFlake :: ( + HasCallStack, MonadUnliftIO m, MonadLogger m, MonadReader context m + , HasBaseContext context, HasBootstrapNixpkgs context + ) => String -> m FilePath +testBuildUsingFlake expr = do + rootDir <- findFirstParentMatching (\x -> doesPathExist (x ".git")) + let cp = (proc "nix" ["build", expr, "--no-link", "--json"]) { + cwd = Just rootDir + , std_err = CreatePipe + } + out <- readCreateProcessWithLogging cp "" + case parseNixBuildJson <$> (A.eitherDecode (BL8.pack out)) of + Left err -> expectationFailure [i|Failed to parse bin paths: #{err}. JSON: #{out}|] + Right Nothing -> expectationFailure [i|Didn't find Nix output in: #{out}|] + Right (Just output) -> pure $ T.unpack output testEval :: ( HasCallStack, MonadUnliftIO m, MonadLogger m, MonadReader context m diff --git a/tests/src/TestLib/TestSearchers.hs b/tests/src/TestLib/TestSearchers.hs index 4bc4a70..e0a6f84 100644 --- a/tests/src/TestLib/TestSearchers.hs +++ b/tests/src/TestLib/TestSearchers.hs @@ -3,6 +3,7 @@ module TestLib.TestSearchers where import Conduit as C +import Control.Monad import Control.Monad.Catch (MonadMask) import Control.Monad.Logger import Control.Monad.Reader @@ -17,8 +18,6 @@ import System.FilePath import Test.Sandwich import TestLib.TestBuilding import TestLib.Types -import TestLib.Util -import UnliftIO.Directory import UnliftIO.IO import UnliftIO.Process @@ -30,7 +29,7 @@ testKernelSearchersBuild :: ( , HasBaseContext context, HasBootstrapNixpkgs context ) => Text -> SpecFree context m () testKernelSearchersBuild kernel = it [i|#{kernel}: package searchers build|] $ do - testBuild [i|kernels."#{kernel}".packageSearch|] + void $ testBuild [i|kernels."#{kernel}".packageSearch|] testHasExpectedFields :: ( MonadIO m, MonadMask m, MonadUnliftIO m, MonadBaseControl IO m @@ -75,20 +74,11 @@ searcherResults :: ( , HasBaseContext context, HasBootstrapNixpkgs context ) => String -> m [A.Object] searcherResults expr = do - rootDir <- findFirstParentMatching (\x -> doesPathExist (x ".git")) - - env <- getEnvWithNixPath - let cp = (proc "nix-build" [".", "-A", expr, "--no-out-link"]) { - cwd = Just rootDir - , std_err = CreatePipe - , env = Just env - } - built <- (T.unpack . T.strip . T.pack) <$> (readCreateProcessWithLogging cp "") + built <- testBuild expr info [i|Got built searcher: #{built}|] let cp' = (proc (built "bin" "searcher") []) { - cwd = Just rootDir - , std_in = CreatePipe + std_in = CreatePipe , std_out = CreatePipe , std_err = CreatePipe , create_group = True diff --git a/tests/tests.cabal b/tests/tests.cabal index 16b2136..656edc1 100644 --- a/tests/tests.cabal +++ b/tests/tests.cabal @@ -111,6 +111,7 @@ executable tests Spec.Tests.Rust.Diagnostics Spec.Tests.Rust.Hovers Spec.Tests.Searchers + Spec.Tests.SettingsSchemas Spec.Tests.Shells.Zsh Spec.Tests.Spellchecker Paths_tests