packages feed

dotenv 0.1.0.9 → 0.2.0.0

raw patch · 8 files changed

+141/−62 lines, 8 filesdep +megaparsecdep +textdep −parsecdep −parseerror-eqdep ~basedep ~optparse-applicative

Dependencies added: megaparsec, text

Dependencies removed: parsec, parseerror-eq

Dependency ranges changed: base, optparse-applicative

Files

+ CHANGELOG.md view
@@ -0,0 +1,10 @@+## Dotenv 0.2.0.0++* Changed public interfaces to use Data.Text.+* Added function `parseFile` to read dotenv file without modifying the+  environment. Thanks to Daisuke Fujimura (Github: fujimura) for making this+  contribution.+  +## Dotenv 0.1.0.0++* First public release.
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2015 Justin Leitgeb+Copyright (c) 2016 Justin Leitgeb  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
dotenv.cabal view
@@ -1,5 +1,5 @@ name:                dotenv-version:             0.1.0.9+version:             0.2.0.0 synopsis:            Loads environment variables from dotenv files homepage:            https://github.com/stackbuilders/dotenv-hs description:@@ -34,23 +34,26 @@ license:             MIT license-file:        LICENSE author:              Justin Leitgeb-maintainer:          justin@stackbuilders.com-copyright:           2015 Stack Builders Inc.+maintainer:          hackage@stackbuilders.com+copyright:           2015-2016 Stack Builders Inc. category:            Configuration build-type:          Simple-extra-source-files:  spec/fixtures/.dotenv+extra-source-files:    spec/fixtures/.dotenv+                     , CHANGELOG.md cabal-version:       >=1.10 bug-reports:         https://github.com/stackbuilders/dotenv-hs/issues  executable dotenv   main-is:             Main.hs-  -- other-modules:+  other-modules:       Configuration.Dotenv+                       Configuration.Dotenv.Parse   -- other-extensions:-  build-depends:         base >=4.5 && <4.9+  build-depends:         base >=4.5 && <5.0                        , base-compat >= 0.4-                       , optparse-applicative >=0.12 && < 0.13-                       , parsec >= 3.1.0 && <= 3.2+                       , optparse-applicative >=0.11 && < 0.13+                       , megaparsec >= 4.2.0 && < 4.5.0                        , process+                       , text    hs-source-dirs:      src   default-language:    Haskell2010@@ -59,9 +62,10 @@   exposed-modules:    Configuration.Dotenv.Parse                     , Configuration.Dotenv -  build-depends:         base >=4.5 && <4.9+  build-depends:         base >=4.5 && <5.0                        , base-compat >= 0.4-                       , parsec >= 3.1.0 && <= 3.2+                       , megaparsec >= 4.2.0 && < 4.5.0+                       , text    hs-source-dirs:      src   default-language:    Haskell2010@@ -74,12 +78,14 @@   main-is: Spec.hs   other-modules:         Configuration.DotenvSpec                        , Configuration.Dotenv.ParseSpec+                       , Configuration.Dotenv+                       , Configuration.Dotenv.Parse -  build-depends:       base >=4.5 && <4.9-                       , base-compat >= 0.4-                       , parsec >= 3.1.0 && <= 3.2-                       , parseerror-eq-                       , hspec+  build-depends:       base >=4.5 && <5.0+                     , base-compat >= 0.4+                     , megaparsec >= 4.2.0 && < 4.5.0+                     , text+                     , hspec    default-language:    Haskell2010   ghc-options:         -Wall
spec/Configuration/Dotenv/ParseSpec.hs view
@@ -1,15 +1,19 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE OverloadedStrings #-} -module Configuration.Dotenv.ParseSpec (spec) where+module Configuration.Dotenv.ParseSpec (main, spec) where  import Configuration.Dotenv.Parse (configParser) -import Test.Hspec (it, describe, shouldBe, Spec)+import Test.Hspec (it, describe, shouldBe, Spec, hspec) -import Text.Parsec (ParseError, parse)+import Text.Megaparsec (ParseError, parse) -import Text.ParseErrorEq ()+import qualified Data.Text as T +main :: IO ()+main = hspec spec+ spec :: Spec spec = describe "parse" $ do   it "parses unquoted values" $@@ -44,7 +48,7 @@   it "does not parse variables with hyphens in the name" $     isLeft (parseConfig "FOO-BAR=foobar") `shouldBe` True -  it "parses variables with '_' in the name" $+  it "parses variables with \"_\" in the name" $     parseConfig "FOO_BAR=foobar" `shouldBe` Right [("FOO_BAR", "foobar")]    it "parses variables with digits after the first character" $@@ -69,7 +73,7 @@   it "ignores inline comments after quoted arguments" $     parseConfig "FOO=\"bar\" # this is foo" `shouldBe` Right [("FOO", "bar")] -  it "allows # in quoted values" $+  it "allows \"#\" in quoted values" $     parseConfig "foo=\"bar#baz\" # comment" `shouldBe`     Right [("foo", "bar#baz")] @@ -85,5 +89,5 @@ isLeft ( Left _ ) = True isLeft _          = False -parseConfig :: String -> Either ParseError [(String, String)]+parseConfig :: T.Text -> Either ParseError [(T.Text, T.Text)] parseConfig = parse configParser "(unknown)"
spec/Configuration/DotenvSpec.hs view
@@ -1,13 +1,19 @@-module Configuration.DotenvSpec (spec) where+{-# LANGUAGE OverloadedStrings #-} -import Configuration.Dotenv (load, loadFile)+module Configuration.DotenvSpec (main, spec) where +import Configuration.Dotenv (load, loadFile, parseFile)+ import Test.Hspec  import System.Environment.Compat (lookupEnv, setEnv, unsetEnv)+import Control.Monad (liftM) -{-# ANN module "HLint: ignore Reduce duplication" #-}+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} +main :: IO ()+main = hspec spec+ spec :: Spec spec = do   describe "load" $ after_ (unsetEnv "foo") $ do@@ -53,3 +59,16 @@       loadFile True "spec/fixtures/.dotenv"        lookupEnv "DOTENV" `shouldReturn` Just "true"++  describe "parseFile" $ after_ (unsetEnv "DOTENV") $ do+    it "returns variables from a file without changing the environment" $ do+      lookupEnv "DOTENV" `shouldReturn` Nothing++      liftM head (parseFile "spec/fixtures/.dotenv") `shouldReturn`+        ("DOTENV", "true")++      lookupEnv "DOTENV" `shouldReturn` Nothing++    it "recognizes unicode characters" $+      liftM (!! 1) (parseFile "spec/fixtures/.dotenv") `shouldReturn`+        ("UNICODE_TEST", "Manabí")
spec/fixtures/.dotenv view
@@ -1,1 +1,2 @@ DOTENV=true+UNICODE_TEST=Manabí
src/Configuration/Dotenv.hs view
@@ -1,16 +1,29 @@-module Configuration.Dotenv (load, loadFile) where+-- |+-- Module      :  Configuration.Dotenv+-- Copyright   :  © 2015–2016 Stack Builders Inc.+-- License     :  MIT+--+-- Maintainer  :  Stack Builders <hackage@stackbuilders.com>+-- Stability   :  experimental+-- Portability :  portable+--+-- This module contains common functions to load and read dotenv files. +module Configuration.Dotenv (load, loadFile, parseFile) where+ import System.Environment.Compat (lookupEnv, setEnv)  import Configuration.Dotenv.Parse (configParser) -import Text.Parsec (parse)+import Text.Megaparsec (parse) +import qualified Data.Text as T+ -- | Loads the given list of options into the environment. Optionally -- override existing variables with values from Dotenv files. load ::   Bool -- ^ Override existing settings?-  -> [(String, String)] -- ^ List of values to be set in environment+  -> [(T.Text, T.Text)] -- ^ List of values to be set in environment   -> IO () load override = mapM_ (applySetting override) @@ -20,22 +33,31 @@   Bool        -- ^ Override existing settings?   -> FilePath -- ^ A file containing options to load into the environment   -> IO ()-loadFile override f = do+loadFile override f = load override =<< parseFile f++-- | Parses the given dotenv file and returns values /without/ adding them to+-- the environment.+parseFile ::+  FilePath -- ^ A file containing options to read+  -> IO [(T.Text, T.Text)] -- ^ Variables contained in the file+parseFile f = do   contents <- readFile f -  case parse configParser f contents of+  case parse configParser f (T.pack contents) of     Left e        -> error $ "Failed to read file" ++ show e-    Right options -> load override options-+    Right options -> return options -applySetting :: Bool -> (String, String) -> IO ()+applySetting :: Bool -> (T.Text, T.Text) -> IO () applySetting override (key, value) =   if override then-    setEnv key value+    setEnv key' value'    else do-    res <- lookupEnv key+    res <- lookupEnv key'      case res of-      Nothing -> setEnv key value+      Nothing -> setEnv key' value'       Just _  -> return ()++    where key'   = T.unpack key+          value' = T.unpack value
src/Configuration/Dotenv/Parse.hs view
@@ -1,67 +1,84 @@+-- |+-- Module      :  Configuration.Dotenv.Parse+-- Copyright   :  © 2015–2016 Stack Builders Inc.+-- License     :  MIT+--+-- Maintainer  :  Stack Builders <hackage@stackbuilders.com>+-- Stability   :  experimental+-- Portability :  portable+--+-- Parser for files in dotenv format. These files generally consist of lines+-- with the form key=value. Comments and blank lines are also supported. More+-- information on the dotenv format can be found in the project README and the+-- test suite.+ module Configuration.Dotenv.Parse (configParser) where -import Text.Parsec ((<|>), (<?>), anyChar, char, many, manyTill, try)-import Text.Parsec.Combinator (eof)-import Text.Parsec.String (Parser)-import Text.ParserCombinators.Parsec.Char-  (digit, letter, newline, noneOf, oneOf)+import Text.Megaparsec ((<?>), anyChar, char, eof, manyTill, try)+import Text.Megaparsec.Text (Parser)+import Text.Megaparsec.Char+  (digitChar, letterChar, newline, noneOf, oneOf) -import Control.Applicative ((<*), (*>), (<$>))+import Control.Applicative+import Prelude+ import Data.Maybe (catMaybes)-import Control.Monad (liftM2)+import Control.Monad (liftM, liftM2) +import qualified Data.Text as T+ -- | Returns a parser for a Dotenv configuration file.  Accepts key -- and value arguments separated by "=".  Comments are allowed on -- lines by themselves and on blank lines.-configParser :: Parser [(String, String)]+configParser :: Parser [(T.Text, T.Text)] configParser = catMaybes <$> many envLine <* eof  -envLine :: Parser (Maybe (String, String))+envLine :: Parser (Maybe (T.Text, T.Text)) envLine = (comment <|> blankLine) *> return Nothing <|> Just <$> optionLine -blankLine :: Parser String-blankLine = many verticalSpace <* newline <?> "blank line"+blankLine :: Parser T.Text+blankLine = liftM T.pack (many verticalSpace <* newline) <?> "blank line" -optionLine :: Parser (String, String)+optionLine :: Parser (T.Text, T.Text) optionLine = liftM2 (,)   (many verticalSpace *> variableName <* variableValueSeparator)   value  -- | Variables must start with a letter or underscore, and may contain -- letters, digits or '_' character after the first character.-variableName :: Parser String-variableName = liftM2 (:) (letter <|> char '_')-  (many (letter <|> char '_' <|> digit <?>+variableName :: Parser T.Text+variableName = liftM T.pack (liftM2 (:) (letterChar <|> char '_')+  (many (letterChar <|> char '_' <|> digitChar <?>          unwords [ "valid non-leading shell variable character (alphanumeric,"-                 , "digit or underscore)" ]))+                 , "digit or underscore)" ])))    <?> unwords [ "shell variable name (letter or underscore followed"               , "by alphanumeric characters or underscores)" ] -value :: Parser String+value :: Parser T.Text value = quotedValue <|> unquotedValue <?> "variable value" -quotedValue :: Parser String+quotedValue :: Parser T.Text quotedValue = (quotedWith '\'' <|> quotedWith '\"')   <* (comment *> return () <|> many verticalSpace *> endOfLineOrInput)   <?> "variable value surrounded with single or double quotes" -unquotedValue :: Parser String+unquotedValue :: Parser T.Text unquotedValue =-  manyTill anyChar (comment <|> many verticalSpace <* endOfLineOrInput)+  liftM T.pack (manyTill anyChar (liftM T.unpack comment <|> many verticalSpace <* endOfLineOrInput))  -- | Based on a commented-string parser in: -- http://hub.darcs.net/navilan/XMonadTasks/raw/Data/Config/Lexer.hs-quotedWith :: Char -> Parser String-quotedWith c = char c *> many chr <* (char c <?> "closing quote character")+quotedWith :: Char -> Parser T.Text+quotedWith c = liftM T.pack (char c *> many chr <* (char c <?> "closing quote character"))    where chr = esc <|> noneOf [c]         esc = escape *> char c <?> "escape character" -comment :: Parser String-comment = try (many verticalSpace *> char '#')-          *> manyTill anyChar endOfLineOrInput+comment :: Parser T.Text+comment = liftM T.pack (try (many verticalSpace *> char '#')+          *> manyTill anyChar endOfLineOrInput)           <?> "comment"  endOfLineOrInput :: Parser ()