packages feed

servant-cassava 0.9 → 0.10

raw patch · 3 files changed

+112/−23 lines, 3 filesdep +servant-cassavadep +servant-serverdep +waidep ~basedep ~base-compatdep ~cassavaPVP ok

version bump matches the API change (PVP)

Dependencies added: servant-cassava, servant-server, wai, warp

Dependency ranges changed: base, base-compat, cassava, servant

API changes (from Hackage documentation)

- Servant.CSV.Cassava: class DecodeOpts a
- Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromNamedRecord a, Servant.CSV.Cassava.DecodeOpts opt) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' 'Data.Csv.Types.HasHeader opt) (Data.Csv.Types.Header, Data.Vector.Vector a)
- Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromNamedRecord a, Servant.CSV.Cassava.DecodeOpts opt) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' 'Data.Csv.Types.HasHeader opt) (Data.Csv.Types.Header, [a])
- Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromRecord a, Servant.CSV.Cassava.DecodeOpts opt, Servant.CSV.Cassava.SHasHeaderI hasHeader) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' hasHeader opt) (Data.Vector.Vector a)
- Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromRecord a, Servant.CSV.Cassava.DecodeOpts opt, Servant.CSV.Cassava.SHasHeaderI hasHeader) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' hasHeader opt) [a]
- Servant.CSV.Cassava: instance Servant.API.ContentTypes.Accept (Servant.CSV.Cassava.CSV' hasHeader opt)
- Servant.CSV.Cassava: instance Servant.CSV.Cassava.DecodeOpts Servant.CSV.Cassava.DefaultOpts
+ Servant.CSV.Cassava: csvContentType :: EncodeOpts opt => Proxy opt -> MediaType
+ Servant.CSV.Cassava: data TabSeparatedOpts
+ Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromNamedRecord a, Servant.CSV.Cassava.EncodeOpts opt) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' 'Data.Csv.Types.HasHeader opt) (Data.Csv.Types.Header, Data.Vector.Vector a)
+ Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromNamedRecord a, Servant.CSV.Cassava.EncodeOpts opt) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' 'Data.Csv.Types.HasHeader opt) (Data.Csv.Types.Header, [a])
+ Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromRecord a, Servant.CSV.Cassava.EncodeOpts opt, Servant.CSV.Cassava.SHasHeaderI hasHeader) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' hasHeader opt) (Data.Vector.Vector a)
+ Servant.CSV.Cassava: instance (Data.Csv.Conversion.FromRecord a, Servant.CSV.Cassava.EncodeOpts opt, Servant.CSV.Cassava.SHasHeaderI hasHeader) => Servant.API.ContentTypes.MimeUnrender (Servant.CSV.Cassava.CSV' hasHeader opt) [a]
+ Servant.CSV.Cassava: instance GHC.Generics.Generic Servant.CSV.Cassava.TabSeparatedOpts
+ Servant.CSV.Cassava: instance Servant.CSV.Cassava.EncodeOpts Servant.CSV.Cassava.TabSeparatedOpts
+ Servant.CSV.Cassava: instance Servant.CSV.Cassava.EncodeOpts opt => Servant.API.ContentTypes.Accept (Servant.CSV.Cassava.CSV' hasHeader opt)
- Servant.CSV.Cassava: class EncodeOpts opt
+ Servant.CSV.Cassava: class EncodeOpts opt where decodeOpts p = DecodeOptions {decDelimiter = encDelimiter e} where e = encodeOpts p csvContentType p = case encDelimiter (encodeOpts p) of { 9 -> "text" // "tab-separated-values" /: ("charset", "utf-8") _ -> "text" // "csv" /: ("charset", "utf-8") }
- Servant.CSV.Cassava: decodeOpts :: DecodeOpts a => Proxy a -> DecodeOptions
+ Servant.CSV.Cassava: decodeOpts :: EncodeOpts opt => Proxy opt -> DecodeOptions

Files

+ example/Main.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE DataKinds       #-}+{-# LANGUAGE DeriveGeneric   #-}+{-# LANGUAGE TypeOperators   #-}+module Main (main, Foo (..)) where++import Prelude        ()+import Prelude.Compat++import Data.Csv           (DefaultOrdered, FromRecord, ToNamedRecord, ToRecord)+import Data.Maybe         (fromMaybe)+import GHC.Generics       (Generic)+import Network.Wai        (Application)+import Servant+import Servant.CSV.Cassava+import System.Environment (getArgs, lookupEnv)+import Text.Read          (readMaybe)++import qualified Network.Wai.Handler.Warp as Warp++data Foo = Foo+    { fooName :: String+    , fooNum  :: Int+    }+  deriving (Eq, Show, Generic)++instance DefaultOrdered Foo+instance FromRecord Foo+instance ToNamedRecord Foo+instance ToRecord Foo++type API = "post" :> ReqBody '[CSV] [Foo] :> Post '[CSV] [Foo]+      :<|> "csv" :> Get '[CSV] [Foo]+      :<|> "tsv" :> Get '[CSV' 'NoHeader TabSeparatedOpts] [Foo]++api :: Proxy API+api = Proxy++server :: Server API+server = pure :<|> pure [Foo "Csv!" 42] :<|> pure [Foo "Tsv!" 7]++app :: Application+app = serve api server++main :: IO ()+main = do+    args <- getArgs+    case args of+        ("run":_) -> do+            port <- fromMaybe 8000 . (>>= readMaybe) <$> lookupEnv "PORT"+            Warp.run port app+        _ -> putStrLn "To run, pass run argument"
servant-cassava.cabal view
@@ -1,5 +1,5 @@ name:                servant-cassava-version:             0.9+version:             0.10 synopsis:            Servant CSV content-type for cassava description:         Servant CSV content-type for cassava. homepage:            http://haskell-servant.readthedocs.org/@@ -8,10 +8,15 @@ author:              Servant Contributors maintainer:          haskell-servant-maintainers@googlegroups.com copyright:           2015-2016 Servant Contributors-category:            Web+category:            Web, Servant, CSV build-type:          Simple cabal-version:       >=1.10 bug-reports:         http://github.com/haskell-servant/servant-cassava/issues+tested-with:+  GHC==7.8.4,+  GHC==7.10.3,+  GHC==8.0.2,+  GHC==8.2.1  source-repository head   type: git@@ -19,13 +24,32 @@  library   exposed-modules:     Servant.CSV.Cassava-  build-depends:       base >=4.6 && <5+  build-depends:       base >=4.7 && <5                      , base-compat >=0.9.1 && <0.10                      , bytestring-                     , cassava >0.4 && <0.5-                     , servant >=0.7 && <0.12+                     , cassava >=0.4.3 && <0.6+                     , servant >=0.7 && <0.13                      , http-media                      , vector   hs-source-dirs:      src   default-language:    Haskell2010   ghc-options: -Wall++test-suite example+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs:+    example+  ghc-options: -Wall+  build-depends:+      base+    , base-compat+    , bytestring+    , http-media+    , servant+    , cassava+    , servant-cassava+    , servant-server >=0.4.4.5  && <0.13+    , wai            >=3.0.3.0  && <3.3+    , warp           >=3.0.13.1 && <3.3+  default-language: Haskell2010
src/Servant/CSV/Cassava.hs view
@@ -56,13 +56,16 @@ lowerSHasHeader SHasHeader = HasHeader lowerSHasHeader SNoHeader  = NoHeader --- | Default options, instances providing 'defaultDecodeOptions' and 'defaultEncodeOptions'.+-- | Default options, instances providing 'defaultDecodeOptions' and 'defaultEncodeOptions', and content type @text/csv;charset=utf-8@ data DefaultOpts deriving (Typeable, Generic) --- | @text/csv;charset=utf-8@-instance Accept (CSV' hasHeader opt) where-    contentType _ = "text" M.// "csv" M./: ("charset", "utf-8")+-- | Options that work for tab delimited data, with content type @text/tab-separated-values;charset=utf-8@+data TabSeparatedOpts deriving (Typeable, Generic) +-- | Content type can be determined to coincide with encode opts.+instance EncodeOpts opt => Accept (CSV' hasHeader opt) where+    contentType _ = csvContentType (Proxy :: Proxy opt)+ -- * Encoding  -- ** Instances@@ -114,11 +117,24 @@       where         opts = encodeOpts (Proxy :: Proxy opt) --- ** Encode Options+-- ** Encode/Decode Options  class EncodeOpts opt where     encodeOpts :: Proxy opt -> EncodeOptions +    decodeOpts :: Proxy opt -> DecodeOptions+    decodeOpts p = DecodeOptions+        { decDelimiter = encDelimiter e+        }+      where+        e = encodeOpts p++    csvContentType :: Proxy opt -> M.MediaType+    csvContentType p = case encDelimiter (encodeOpts p) of+        -- ord '\t' = 9+        9 -> "text" M.// "tab-separated-values" M./: ("charset", "utf-8")+        _ -> "text" M.// "csv" M./: ("charset", "utf-8")+ encodeOpts'     :: forall opt hasHeader.  (EncodeOpts opt, SHasHeaderI hasHeader)     => Proxy opt -> Proxy hasHeader -> EncodeOptions@@ -128,43 +144,41 @@  instance EncodeOpts DefaultOpts where     encodeOpts _ = defaultEncodeOptions+    decodeOpts _ = defaultDecodeOptions +instance EncodeOpts TabSeparatedOpts where+    -- ord '\t' = 9+    encodeOpts _ = defaultEncodeOptions { encDelimiter = 9 }+    decodeOpts _ = defaultDecodeOptions { decDelimiter = 9 }++ -- * Decoding  -- ** Instances  -- | Decode with 'decodeByNameWith'.-instance ( FromNamedRecord a, DecodeOpts opt+instance ( FromNamedRecord a, EncodeOpts opt          ) => MimeUnrender (CSV' 'HasHeader opt) (Header, [a]) where     mimeUnrender _ bs = fmap toList <$> decodeByNameWith (decodeOpts p) bs       where p = Proxy :: Proxy opt  -- | Decode with 'decodeWith'.-instance ( FromRecord a, DecodeOpts opt, SHasHeaderI hasHeader+instance ( FromRecord a, EncodeOpts opt, SHasHeaderI hasHeader          ) => MimeUnrender (CSV' hasHeader opt) [a] where     mimeUnrender _  = fmap toList . decodeWith (decodeOpts p) (lowerSHasHeader sh)       where         p = Proxy :: Proxy opt         sh = shasheader :: SHasHeader hasHeader -instance ( FromNamedRecord a, DecodeOpts opt+instance ( FromNamedRecord a, EncodeOpts opt          ) => MimeUnrender (CSV' 'HasHeader opt) (Header, Vector a) where     mimeUnrender _ = decodeByNameWith (decodeOpts p)       where p = Proxy :: Proxy opt  -- | Decode with 'decodeWith'.-instance ( FromRecord a, DecodeOpts opt, SHasHeaderI hasHeader+instance ( FromRecord a, EncodeOpts opt, SHasHeaderI hasHeader          ) => MimeUnrender (CSV' hasHeader opt) (Vector a) where     mimeUnrender _ = decodeWith (decodeOpts p) (lowerSHasHeader sh)       where         p = Proxy :: Proxy opt         sh = shasheader :: SHasHeader hasHeader----- ** Decode Options--class DecodeOpts a where-    decodeOpts :: Proxy a -> DecodeOptions--instance DecodeOpts DefaultOpts where-    decodeOpts _ = defaultDecodeOptions