packages feed

conferer 1.0.0.0 → 1.0.0.1

raw patch · 8 files changed

+97/−6 lines, 8 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ Conferer: mkConfig' :: Defaults -> [SourceCreator] -> IO Config
+ Conferer.Config: addSources :: [SourceCreator] -> Config -> IO Config
+ Conferer.Config: type Defaults = [(Key, Dynamic)]
+ Conferer.Config.Internal: addSources :: [SourceCreator] -> Config -> IO Config
+ Conferer.FromConfig.Internal: unFile :: File -> FilePath

Files

CHANGELOG.md view
@@ -8,9 +8,25 @@  Nothing +## [v1.0.0.1] - 2021-01-17++### Fixed++* In the `File`'s `FromConfig` instance, if the default is present and it's type+is `File`, it throws, which doesn't follow the rest of the library.++### Added++* Add `mkConfig'` which allows creating a config by passing a list of defaults and+a list of source creators.+* Add `addSources`, which allows to add several sources to a config.+* Define the type `Defaults`, which is a list of associations from `Key` to+`Dynamic`.+ ## [v1.0.0.0] - 2020-12-29  First release  [Unreleased]: https://github.com/ludat/conferer/compare/conferer_v1.0.0.0...HEAD [v1.0.0.0]: https://github.com/ludat/conferer/releases/tag/v0.0.0.0...conferer_v1.0.0.0+[v1.0.0.1]: https://github.com/ludat/conferer/releases/tag/conferer_v1.0.0.0...conferer_v1.0.0.1
conferer.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: d0ab7e2b51d28b44a470332f5c24414b3d885483251fb269e6f5e18c00993788+-- hash: e95018cf9b8ebe424a2926412853affcae168760a3b9ea0530fbf3a4c1d83b14  name:           conferer-version:        1.0.0.0+version:        1.0.0.1 synopsis:       Configuration management library  description:    Library to abstract the parsing of many haskell config values from different config sources@@ -82,6 +82,7 @@       Conferer.Source.NamespacedSpec       Conferer.Source.NullSpec       Conferer.Source.PropertiesFileSpec+      ConfererSpec       Spec       Paths_conferer   hs-source-dirs:
src/Conferer.hs view
@@ -16,6 +16,7 @@    -- * Creating a Config   mkConfig+  , mkConfig'   -- * Getting values from a config   -- | These functions allow you to get any type that implements 'FromConfig'   , fetch@@ -40,6 +41,7 @@ import qualified Conferer.Source.Env as Env import qualified Conferer.Source.CLIArgs as Cli import qualified Conferer.Source.PropertiesFile as PropertiesFile+import Conferer.Config (Defaults)  -- | Use the 'FromConfig' instance to get a value of type @a@ from the config --   using some default fallback. The most common use for this is creating a custom@@ -80,3 +82,10 @@   >>= addSource (Cli.fromConfig)   >>= addSource (Env.fromConfig appName)   >>= addSource (PropertiesFile.fromConfig "config.file")++-- | Create a 'Config' with the given defaults and source creators.+--   The sources will take precedence by the order they have in the list (earlier in+--   the list means it's tried first).+--   If the requested key is not found in any source it'll be looked up in the defaults.+mkConfig' :: Defaults -> [SourceCreator] -> IO Config+mkConfig' defaults sources = addSources sources . addDefaults defaults $ emptyConfig
src/Conferer/Config.hs view
@@ -17,9 +17,11 @@     -- * Config creation and initialization   , emptyConfig   , addSource+  , addSources   , addDefault   , addDefaults   , addKeyMappings+  , Defaults     -- * Re-Exports   , module Conferer.Key   , (&)@@ -29,3 +31,6 @@ import Conferer.Config.Internal.Types import Conferer.Key import Data.Function+import Data.Dynamic (Dynamic)++type Defaults = [(Key, Dynamic)]
src/Conferer/Config/Internal.hs view
@@ -13,7 +13,7 @@ {-# LANGUAGE FlexibleContexts #-} module Conferer.Config.Internal where -import Control.Monad (forM, msum)+import Control.Monad (foldM, forM, msum) import Data.Dynamic import Data.List (sort, nub, union) import Data.Text (Text)@@ -213,6 +213,11 @@     config     { configSources = configSources config ++ [ newSource ]     }++-- | Instantiate several 'Source's using a 'SourceCreator's and a 'Config' and add+--   them to the config in the order defined by the list+addSources :: [SourceCreator] -> Config -> IO Config+addSources sources config = foldM (flip addSource) config sources  -- orElse :: IO KeyLookupResult -> IO KeyLookupResult -> IO KeyLookupResult -- orElse getKey1 getKey2 = do
src/Conferer/FromConfig/Internal.hs view
@@ -176,11 +176,17 @@   File FilePath   deriving (Show, Eq, Ord, Read) +unFile :: File -> FilePath+unFile (File f) = f+ instance IsString File where   fromString s = File s  instance FromConfig File where-  fetchFromConfig key config = do+  fetchFromConfig key config' = do+    defaultPath <- fetchFromDefaults @File key config'+    let config = removeDefault key config'+     filepath <- fetchFromConfig @(Maybe String) key config      extension <- fetchFromConfig @(Maybe String) (key /. "extension") config@@ -194,7 +200,7 @@         $ applyIfPresent FilePath.replaceBaseName basename         $ applyIfPresent FilePath.replaceExtension extension         $ applyIfPresent FilePath.replaceFileName filename-        $ fromMaybe "" filepath+        $ fromMaybe (unFile $ fromMaybe "" defaultPath) filepath     if FilePath.isValid constructedFilePath       then return $ File constructedFilePath       else throwMissingRequiredKeys @String
test/Conferer/FromConfig/FileSpec.hs view
@@ -11,6 +11,8 @@ spec = do   context "File fromConfig" $ do     describe "fetching a File from config" $ do+      ensureFetchParses @File [] [("", toDyn $ File "file.png")] $+        File "file.png"       ensureFetchThrows @File [] [] $         aMissingRequiredKeys @String           [ "some.key"@@ -21,7 +23,7 @@           ]        ensureFetchThrows @File [] [("", toDyn False)] $-        aTypeMismatchWithDefaultError @String "some.key" False+        aTypeMismatchWithDefaultError @File "some.key" False       context "with whole path in root" $ do         ensureFetchParses @File           [ ("", pack $ "some" </> "file.png")
+ test/ConfererSpec.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE TypeApplications #-}+-- {-# LANGUAGE DeriveGeneric #-}+-- {-# LANGUAGE TypeApplications #-}++module ConfererSpec where++import Test.Hspec++import Data.Text (Text)+import Conferer.FromConfig ( FromConfig(fetchFromConfig) )+import Conferer.Source.InMemory (fromConfig)+import Data.Dynamic (toDyn)+import Conferer.Config (Config)+import Conferer (mkConfig', Key)++spec :: Spec+spec = do+  describe "mkConfig'" $ do+    let a = fromConfig [("keyPresentInBoth", "valueInA"), ("keyPresentOnlyInA", "valueInA")]+        b = fromConfig [("keyPresentInBoth", "valueInB"), ("keyPresentOnlyInB", "valueInB")]+        shouldHaveKeyWithValue :: Config -> Key -> Text -> Expectation+        shouldHaveKeyWithValue config key expected = do+          actual <- fetchFromConfig key config+          actual `shouldBe` expected+    describe "the precedence of the sources is defined by the order in the list" $ do+      it "if several sources have a value for the key, the first source in the list that has it is used" $ do+        config <- mkConfig' [] [a, b]++        config `shouldHaveKeyWithValue` "keyPresentInBoth" $ "valueInA"+      it "if only one source has a value for the key, that source is used" $ do+        config <- mkConfig' [] [a, b]++        config `shouldHaveKeyWithValue` "keyPresentOnlyInB" $ "valueInB"+      it "if the key is not present in any source, it doesn't retrieve any value" $ do+        config <- mkConfig' [] [a, b]++        value <- fetchFromConfig "keyNotPresentInAnySource" config+        value `shouldBe` (Nothing :: Maybe Text)+    describe "adds the defaults to the config" $ do+      it "if the key is present in a source and in the default, it uses the first source that has it" $ do+        config <- mkConfig' [("keyPresentOnlyInA", toDyn @Text "defaultValue")] [a]++        config `shouldHaveKeyWithValue` "keyPresentOnlyInA" $ "valueInA"+      it "if the key is not present in any source but it's in a default, it uses the default" $ do+        config <- mkConfig' [("keyPresentOnlyInA", toDyn @Text "defaultValue")] [b]++        config `shouldHaveKeyWithValue` "keyPresentOnlyInA" $ "defaultValue"