Hello community,

here is the log from the commit of package ghc-servant-client for 
openSUSE:Factory checked in at 2017-08-31 20:59:13
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-servant-client (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-servant-client.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-servant-client"

Thu Aug 31 20:59:13 2017 rev:2 rq:513485 version:0.11

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-servant-client/ghc-servant-client.changes    
2017-05-10 20:51:09.541416086 +0200
+++ 
/work/SRC/openSUSE:Factory/.ghc-servant-client.new/ghc-servant-client.changes   
    2017-08-31 20:59:15.803812858 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:06:06 UTC 2017 - [email protected]
+
+- Update to version 0.11 revision 1.
+
+-------------------------------------------------------------------

Old:
----
  servant-client-0.9.1.1.tar.gz

New:
----
  servant-client-0.11.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-servant-client.spec ++++++
--- /var/tmp/diff_new_pack.ZDkX7K/_old  2017-08-31 20:59:17.203616182 +0200
+++ /var/tmp/diff_new_pack.ZDkX7K/_new  2017-08-31 20:59:17.231612248 +0200
@@ -19,7 +19,7 @@
 %global pkg_name servant-client
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.9.1.1
+Version:        0.11
 Release:        0
 Summary:        Automatical derivation of querying functions for servant 
webservices
 License:        BSD-3-Clause
@@ -34,18 +34,22 @@
 BuildRequires:  ghc-base64-bytestring-devel
 BuildRequires:  ghc-bytestring-devel
 BuildRequires:  ghc-exceptions-devel
+BuildRequires:  ghc-generics-sop-devel
 BuildRequires:  ghc-http-api-data-devel
 BuildRequires:  ghc-http-client-devel
 BuildRequires:  ghc-http-client-tls-devel
 BuildRequires:  ghc-http-media-devel
 BuildRequires:  ghc-http-types-devel
+BuildRequires:  ghc-monad-control-devel
 BuildRequires:  ghc-mtl-devel
 BuildRequires:  ghc-network-uri-devel
 BuildRequires:  ghc-rpm-macros
 BuildRequires:  ghc-safe-devel
+BuildRequires:  ghc-semigroupoids-devel
 BuildRequires:  ghc-servant-devel
 BuildRequires:  ghc-string-conversions-devel
 BuildRequires:  ghc-text-devel
+BuildRequires:  ghc-transformers-base-devel
 BuildRequires:  ghc-transformers-compat-devel
 BuildRequires:  ghc-transformers-devel
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build

++++++ servant-client-0.9.1.1.tar.gz -> servant-client-0.11.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/CHANGELOG.md 
new/servant-client-0.11/CHANGELOG.md
--- old/servant-client-0.9.1.1/CHANGELOG.md     2016-10-27 13:25:27.000000000 
+0200
+++ new/servant-client-0.11/CHANGELOG.md        2017-05-24 09:22:37.000000000 
+0200
@@ -1,3 +1,37 @@
+0.11
+----
+
+### Other changes
+
+- Path components are escaped
+  ([#696](https://github.com/haskell-servant/servant/pull/696))
+- `Req` `reqPath` field changed from `String` to `BS.Builder`
+  ([#696](https://github.com/haskell-servant/servant/pull/696))
+- Include `Req` in failure errors
+  ([#740](https://github.com/haskell-servant/servant/pull/740))
+
+0.10
+-----
+
+### Breaking changes
+
+There shouldn't be breaking changes. Released as a part of `servant` suite.
+
+### Other changes
+
+* Add MonadBase and MonadBaseControl instances for ClientM
+  ([#663](https://github.com/haskell-servant/servant/issues/663))
+
+* client asks for any content-type in Accept contentTypes non-empty list
+  ([#615](https://github.com/haskell-servant/servant/pull/615))
+
+* Add `ClientLike` class that matches client functions generated using `client`
+  with client data structure.
+  ([#640](https://github.com/haskell-servant/servant/pull/640))
+
+* Allow direct use of 'RequestBody'
+  ([#661](https://github.com/haskell-servant/servant/pull/661))
+
 0.9.1.1
 -------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/servant-client.cabal 
new/servant-client-0.11/servant-client.cabal
--- old/servant-client-0.9.1.1/servant-client.cabal     2016-10-27 
13:25:27.000000000 +0200
+++ new/servant-client-0.11/servant-client.cabal        2017-05-24 
09:22:37.000000000 +0200
@@ -1,5 +1,5 @@
 name:                servant-client
-version:             0.9.1.1
+version:             0.11
 synopsis: automatical derivation of querying functions for servant webservices
 description:
   This library lets you derive automatically Haskell functions that
@@ -13,7 +13,7 @@
 author:              Servant Contributors
 maintainer:          [email protected]
 copyright:           2014-2016 Zalora South East Asia Pte Ltd, Servant 
Contributors
-category:            Web
+category:            Servant Web
 build-type:          Simple
 cabal-version:       >=1.10
 tested-with:         GHC >= 7.8
@@ -30,6 +30,7 @@
 library
   exposed-modules:
     Servant.Client
+    Servant.Client.Generic
     Servant.Client.Experimental.Auth
     Servant.Common.BaseUrl
     Servant.Common.BasicAuth
@@ -37,24 +38,31 @@
   build-depends:
       base                  >= 4.7      && < 4.10
     , base-compat           >= 0.9.1    && < 0.10
-    , aeson                 >= 0.7      && < 1.1
+    , aeson                 >= 0.7      && < 1.3
     , attoparsec            >= 0.12     && < 0.14
     , base64-bytestring     >= 1.0.0.1  && < 1.1
     , bytestring            >= 0.10     && < 0.11
     , exceptions            >= 0.8      && < 0.9
-    , http-api-data         >= 0.3      && < 0.4
+    , generics-sop          >= 0.1.0.0  && < 0.4
+    , http-api-data         >= 0.3.6    && < 0.4
     , http-client           >= 0.4.18.1 && < 0.6
     , http-client-tls       >= 0.2.2    && < 0.4
     , http-media            >= 0.6.2    && < 0.7
     , http-types            >= 0.8.6    && < 0.10
+    , monad-control         >= 1.0.0.4  && < 1.1
     , network-uri           >= 2.6      && < 2.7
     , safe                  >= 0.3.9    && < 0.4
-    , servant               == 0.9.*
+    , semigroupoids         >= 4.3      && < 5.3
+    , servant               == 0.11.*
     , string-conversions    >= 0.3      && < 0.5
     , text                  >= 1.2      && < 1.3
     , transformers          >= 0.3      && < 0.6
+    , transformers-base     >= 0.4.4    && < 0.5
     , transformers-compat   >= 0.4      && < 0.6
     , mtl
+  if !impl(ghc >= 8.0)
+    build-depends:
+        semigroups          >=0.16.2.2 && <0.19
   hs-source-dirs: src
   default-language: Haskell2010
   ghc-options: -Wall
@@ -73,10 +81,8 @@
     , Servant.Common.BaseUrlSpec
   build-depends:
       base == 4.*
-    , base-compat
-    , transformers
-    , transformers-compat
     , aeson
+    , base-compat
     , bytestring
     , deepseq
     , hspec == 2.*
@@ -85,11 +91,15 @@
     , http-media
     , http-types
     , HUnit
+    , mtl
     , network >= 2.6
     , QuickCheck >= 2.7
-    , servant == 0.9.*
+    , servant
     , servant-client
-    , servant-server == 0.9.*
+    , servant-server == 0.11.*
     , text
+    , transformers
+    , transformers-compat
     , wai
     , warp
+    , generics-sop
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/src/Servant/Client/Generic.hs 
new/servant-client-0.11/src/Servant/Client/Generic.hs
--- old/servant-client-0.9.1.1/src/Servant/Client/Generic.hs    1970-01-01 
01:00:00.000000000 +0100
+++ new/servant-client-0.11/src/Servant/Client/Generic.hs       2017-05-24 
09:22:37.000000000 +0200
@@ -0,0 +1,164 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+#include "overlapping-compat.h"
+
+module Servant.Client.Generic
+  ( ClientLike(..)
+  , genericMkClientL
+  , genericMkClientP
+  ) where
+
+import Generics.SOP   (Code, Generic, I(..), NP(..), NS(Z), SOP(..), to)
+import Servant.API    ((:<|>)(..))
+import Servant.Client (ClientM)
+
+-- | This class allows us to match client structure with client functions
+-- produced with 'client' without explicit pattern-matching.
+--
+-- The client structure needs a 'Generics.SOP.Generic' instance.
+--
+-- Example:
+--
+-- > type API
+-- >     = "foo" :> Capture "x" Int :> Get '[JSON] Int
+-- >  :<|> "bar" :> QueryParam "a" Char :> QueryParam "b" String :> Post 
'[JSON] [Int]
+-- >  :<|> Capture "nested" Int :> NestedAPI
+-- >
+-- > type NestedAPI
+-- >     = Get '[JSON] String
+-- >  :<|> "baz" :> QueryParam "c" Char :> Post '[JSON] ()
+-- >
+-- > data APIClient = APIClient
+-- >   { getFoo         :: Int -> ClientM Int
+-- >   , postBar        :: Maybe Char -> Maybe String -> ClientM [Int]
+-- >   , mkNestedClient :: Int -> NestedClient
+-- >   } deriving GHC.Generic
+-- >
+-- > instance Generics.SOP.Generic APIClient
+-- > instance (Client API ~ client) => ClientLike client APIClient
+-- >
+-- > data NestedClient = NestedClient
+-- >  { getString :: ClientM String
+-- >  , postBaz   :: Maybe Char -> ClientM ()
+-- >  } deriving GHC.Generic
+-- >
+-- > instance Generics.SOP.Generic NestedClient
+-- > instance (Client NestedAPI ~ client) => ClientLike client NestedClient
+-- >
+-- > mkAPIClient :: APIClient
+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
+--
+-- By default, left-nested alternatives are expanded:
+--
+-- > type API1
+-- >     = "foo" :> Capture "x" Int :> Get '[JSON] Int
+-- >  :<|> "bar" :> QueryParam "a" Char :> Post '[JSON] String
+-- >
+-- > type API2
+-- >     = "baz" :> QueryParam "c" Char :> Post '[JSON] ()
+-- >
+-- > type API = API1 :<|> API2
+-- >
+-- > data APIClient = APIClient
+-- >   { getFoo  :: Int -> ClientM Int
+-- >   , postBar :: Maybe Char -> ClientM String
+-- >   , postBaz :: Maybe Char -> ClientM ()
+-- >   } deriving GHC.Generic
+-- >
+-- > instance Generics.SOP.Generic APIClient
+-- > instance (Client API ~ client) => ClientLike client APIClient
+-- >
+-- > mkAPIClient :: APIClient
+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
+--
+-- If you want to define client for @API1@ as a separate data structure,
+-- you can use 'genericMkClientP':
+--
+-- > data APIClient1 = APIClient1
+-- >   { getFoo  :: Int -> ClientM Int
+-- >   , postBar :: Maybe Char -> ClientM String
+-- >   } deriving GHC.Generic
+-- >
+-- > instance Generics.SOP.Generic APIClient1
+-- > instance (Client API1 ~ client) => ClientLike client APIClient1
+-- >
+-- > data APIClient = APIClient
+-- >   { mkAPIClient1 :: APIClient1
+-- >   , postBaz      :: Maybe Char -> ClientM ()
+-- >   } deriving GHC.Generic
+-- >
+-- > instance Generics.SOP.Generic APIClient
+-- > instance (Client API ~ client) => ClientLike client APIClient where
+-- >   mkClient = genericMkClientP
+-- >
+-- > mkAPIClient :: APIClient
+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
+class ClientLike client custom where
+  mkClient :: client -> custom
+  default mkClient :: (Generic custom, Code custom ~ '[xs], GClientList client 
'[], GClientLikeL (ClientList client '[]) xs)
+    => client -> custom
+  mkClient = genericMkClientL
+
+instance ClientLike client custom
+      => ClientLike (a -> client) (a -> custom) where
+  mkClient c = mkClient . c
+
+instance ClientLike (ClientM a) (ClientM a) where
+  mkClient = id
+
+-- | Match client structure with client functions, regarding left-nested API 
clients
+-- as separate data structures.
+class GClientLikeP client xs where
+  gMkClientP :: client -> NP I xs
+
+instance (GClientLikeP b (y ': xs), ClientLike a x)
+      => GClientLikeP (a :<|> b) (x ': y ': xs) where
+  gMkClientP (a :<|> b) = I (mkClient a) :* gMkClientP b
+
+instance ClientLike a x => GClientLikeP a '[x] where
+  gMkClientP a = I (mkClient a) :* Nil
+
+-- | Match client structure with client functions, expanding left-nested API 
clients
+-- in the same structure.
+class GClientLikeL (xs :: [*]) (ys :: [*]) where
+  gMkClientL :: NP I xs -> NP I ys
+
+instance GClientLikeL '[] '[] where
+  gMkClientL Nil = Nil
+
+instance (ClientLike x y, GClientLikeL xs ys) => GClientLikeL (x ': xs) (y ': 
ys) where
+  gMkClientL (I x :* xs) = I (mkClient x) :* gMkClientL xs
+
+type family ClientList (client :: *) (acc :: [*]) :: [*] where
+  ClientList (a :<|> b) acc = ClientList a (ClientList b acc)
+  ClientList a acc = a ': acc
+
+class GClientList client (acc :: [*]) where
+  gClientList :: client -> NP I acc -> NP I (ClientList client acc)
+
+instance (GClientList b acc, GClientList a (ClientList b acc))
+  => GClientList (a :<|> b) acc where
+  gClientList (a :<|> b) acc = gClientList a (gClientList b acc)
+
+instance OVERLAPPABLE_ (ClientList client acc ~ (client ': acc))
+  => GClientList client acc where
+  gClientList c acc = I c :* acc
+
+-- | Generate client structure from client type, expanding left-nested API 
(done by default).
+genericMkClientL :: (Generic custom, Code custom ~ '[xs], GClientList client 
'[], GClientLikeL (ClientList client '[]) xs)
+  => client -> custom
+genericMkClientL = to . SOP . Z . gMkClientL . flip gClientList Nil
+
+-- | Generate client structure from client type, regarding left-nested API 
clients as separate data structures.
+genericMkClientP :: (Generic custom, Code custom ~ '[xs], GClientLikeP client 
xs)
+  => client -> custom
+genericMkClientP = to . SOP . Z . gMkClientP
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/src/Servant/Client.hs 
new/servant-client-0.11/src/Servant/Client.hs
--- old/servant-client-0.9.1.1/src/Servant/Client.hs    2016-10-24 
18:27:44.000000000 +0200
+++ new/servant-client-0.11/src/Servant/Client.hs       2017-05-24 
09:22:37.000000000 +0200
@@ -24,6 +24,7 @@
   , ClientEnv (ClientEnv)
   , mkAuthenticateReq
   , ServantError(..)
+  , EmptyClient(..)
   , module Servant.Common.BaseUrl
   ) where
 
@@ -88,6 +89,23 @@
     clientWithRoute (Proxy :: Proxy a) req :<|>
     clientWithRoute (Proxy :: Proxy b) req
 
+-- | Singleton type representing a client for an empty API.
+data EmptyClient = EmptyClient deriving (Eq, Show, Bounded, Enum)
+
+-- | The client for 'EmptyAPI' is simply 'EmptyClient'.
+--
+-- > type MyAPI = "books" :> Get '[JSON] [Book] -- GET /books
+-- >         :<|> "nothing" :> EmptyAPI
+-- >
+-- > myApi :: Proxy MyApi
+-- > myApi = Proxy
+-- >
+-- > getAllBooks :: ClientM [Book]
+-- > (getAllBooks :<|> EmptyClient) = client myApi
+instance HasClient EmptyAPI where
+  type Client EmptyAPI = EmptyClient
+  clientWithRoute Proxy _ = EmptyClient
+
 -- | If you use a 'Capture' in one of your endpoints in your API,
 -- the corresponding querying function will automatically take
 -- an additional argument of the type specified by your 'Capture'.
@@ -406,7 +424,8 @@
   clientWithRoute Proxy req body =
     clientWithRoute (Proxy :: Proxy api)
                     (let ctProxy = Proxy :: Proxy ct
-                     in setRQBody (mimeRender ctProxy body)
+                     in setReqBodyLBS (mimeRender ctProxy body)
+                                  -- We use first contentType from the Accept 
list
                                   (contentType ctProxy)
                                   req
                     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/src/Servant/Common/Req.hs 
new/servant-client-0.11/src/Servant/Common/Req.hs
--- old/servant-client-0.9.1.1/src/Servant/Common/Req.hs        2016-10-27 
13:25:54.000000000 +0200
+++ new/servant-client-0.11/src/Servant/Common/Req.hs   2017-05-24 
09:22:37.000000000 +0200
@@ -1,9 +1,11 @@
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE DeriveGeneric       #-}
-{-# LANGUAGE CPP                 #-}
-{-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving   #-}
+{-# LANGUAGE CPP                        #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
 
 module Servant.Common.Req where
 
@@ -13,21 +15,22 @@
 import Control.Exception
 import Control.Monad
 import Control.Monad.Catch (MonadThrow, MonadCatch)
+import Data.Foldable (toList)
+import Data.Functor.Alt (Alt (..))
+import Data.Semigroup ((<>))
 
-#if MIN_VERSION_mtl(2,2,0)
-import Control.Monad.Except (MonadError(..))
-#else
 import Control.Monad.Error.Class (MonadError(..))
-#endif
 import Control.Monad.Trans.Except
 
-
 import GHC.Generics
+import Control.Monad.Base (MonadBase (..))
 import Control.Monad.IO.Class ()
 import Control.Monad.Reader
-import Data.ByteString.Lazy hiding (pack, filter, map, null, elem)
+import Control.Monad.Trans.Control (MonadBaseControl (..))
+import qualified Data.ByteString.Builder as BS
+import Data.ByteString.Lazy hiding (pack, filter, map, null, elem, any)
 import Data.String
-import Data.String.Conversions
+import Data.String.Conversions (cs)
 import Data.Proxy
 import Data.Text (Text)
 import Data.Text.Encoding
@@ -46,7 +49,8 @@
 
 data ServantError
   = FailureResponse
-    { responseStatus            :: Status
+    { failingRequest            :: UrlReq
+    , responseStatus            :: Status
     , responseContentType       :: MediaType
     , responseBody              :: ByteString
     }
@@ -69,7 +73,7 @@
   deriving (Show, Typeable)
 
 instance Eq ServantError where
-  FailureResponse a b c == FailureResponse x y z =
+  FailureResponse _ a b c == FailureResponse _ x y z =
     (a, b, c) == (x, y, z)
   DecodeFailure a b c == DecodeFailure x y z =
     (a, b, c) == (x, y, z)
@@ -83,10 +87,17 @@
 
 instance Exception ServantError
 
+data UrlReq = UrlReq BaseUrl Req
+
+instance Show UrlReq where
+  show (UrlReq url req) = showBaseUrl url ++ path ++ "?" ++ show (qs req)
+    where
+      path = cs (BS.toLazyByteString (reqPath req))
+
 data Req = Req
-  { reqPath   :: String
+  { reqPath   :: BS.Builder
   , qs        :: QueryText
-  , reqBody   :: Maybe (ByteString, MediaType)
+  , reqBody   :: Maybe (RequestBody, MediaType)
   , reqAccept :: [MediaType]
   , headers   :: [(String, Text)]
   }
@@ -96,7 +107,7 @@
 
 appendToPath :: String -> Req -> Req
 appendToPath p req =
-  req { reqPath = reqPath req ++ "/" ++ p }
+  req { reqPath = reqPath req <> "/" <> toEncodedUrlPiece p }
 
 appendToQueryString :: Text       -- ^ param name
                     -> Maybe Text -- ^ param value
@@ -111,8 +122,31 @@
                                       ++ [(name, decodeUtf8 (toHeader val))]
                              }
 
+-- | Set body and media type of the request being constructed.
+--
+-- The body is set to the given bytestring using the 'RequestBodyLBS'
+-- constructor.
+--
+{-# DEPRECATED setRQBody "Use setReqBodyLBS instead" #-}
 setRQBody :: ByteString -> MediaType -> Req -> Req
-setRQBody b t req = req { reqBody = Just (b, t) }
+setRQBody = setReqBodyLBS
+
+-- | Set body and media type of the request being constructed.
+--
+-- The body is set to the given bytestring using the 'RequestBodyLBS'
+-- constructor.
+--
+-- @since 0.9.2.0
+--
+setReqBodyLBS :: ByteString -> MediaType -> Req -> Req
+setReqBodyLBS b t req = req { reqBody = Just (RequestBodyLBS b, t) }
+
+-- | Set body and media type of the request being constructed.
+--
+-- @since 0.9.2.0
+--
+setReqBody :: RequestBody -> MediaType -> Req -> Req
+setReqBody b t req = req { reqBody = Just (b, t) }
 
 reqToRequest :: (Functor m, MonadThrow m) => Req -> BaseUrl -> m Request
 reqToRequest req (BaseUrl reqScheme reqHost reqPort path) =
@@ -126,12 +160,13 @@
                                          , uriRegName = reqHost
                                          , uriPort = ":" ++ show reqPort
                                          }
-                             , uriPath = path ++ reqPath req
+                             , uriPath = fullPath
                              }
+        fullPath = path ++ cs (BS.toLazyByteString (reqPath req))
 
         setrqb r = case reqBody req of
                      Nothing -> r
-                     Just (b,t) -> r { requestBody = RequestBodyLBS b
+                     Just (b,t) -> r { requestBody = b
                                      , requestHeaders = requestHeaders r
                                                      ++ [(hContentType, cs . 
show $ t)] }
         setQS = setQueryString $ queryTextToQuery (qs req)
@@ -179,11 +214,27 @@
                              , MonadThrow, MonadCatch
                              )
 
+instance MonadBase IO ClientM where
+  liftBase = ClientM . liftBase
+
+instance MonadBaseControl IO ClientM where
+  type StM ClientM a = Either ServantError a
+
+  -- liftBaseWith :: (RunInBase ClientM IO -> IO a) -> ClientM a
+  liftBaseWith f = ClientM (liftBaseWith (\g -> f (g . runClientM')))
+
+  -- restoreM :: StM ClientM a -> ClientM a
+  restoreM st = ClientM (restoreM st)
+
+-- | Try clients in order, last error is preserved.
+instance Alt ClientM where
+  a <!> b = a `catchError` \_ -> b
+
 runClientM :: ClientM a -> ClientEnv -> IO (Either ServantError a)
 runClientM cm env = runExceptT $ (flip runReaderT env) $ runClientM' cm
 
 
-performRequest :: Method -> Req 
+performRequest :: Method -> Req
                -> ClientM ( Int, ByteString, MediaType
                           , [HTTP.Header], Response ByteString)
 performRequest reqMethod req = do
@@ -209,16 +260,16 @@
                    Nothing -> throwError $ InvalidContentTypeHeader (cs t) body
                    Just t' -> pure t'
       unless (status_code >= 200 && status_code < 300) $
-        throwError $ FailureResponse status ct body
+        throwError $ FailureResponse (UrlReq reqHost req) status ct body
       return (status_code, body, ct, hdrs, response)
 
-performRequestCT :: MimeUnrender ct result => Proxy ct -> Method -> Req 
+performRequestCT :: MimeUnrender ct result => Proxy ct -> Method -> Req
     -> ClientM ([HTTP.Header], result)
 performRequestCT ct reqMethod req = do
-  let acceptCT = contentType ct
+  let acceptCTS = contentTypes ct
   (_status, respBody, respCT, hdrs, _response) <-
-    performRequest reqMethod (req { reqAccept = [acceptCT] })
-  unless (matches respCT (acceptCT)) $ throwError $ UnsupportedContentType 
respCT respBody
+    performRequest reqMethod (req { reqAccept = toList acceptCTS })
+  unless (any (matches respCT) acceptCTS) $ throwError $ 
UnsupportedContentType respCT respBody
   case mimeUnrender ct respBody of
     Left err -> throwError $ DecodeFailure err respCT respBody
     Right val -> return (hdrs, val)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/servant-client-0.9.1.1/test/Servant/ClientSpec.hs 
new/servant-client-0.11/test/Servant/ClientSpec.hs
--- old/servant-client-0.9.1.1/test/Servant/ClientSpec.hs       2016-10-24 
18:27:44.000000000 +0200
+++ new/servant-client-0.11/test/Servant/ClientSpec.hs  2017-05-24 
09:22:37.000000000 +0200
@@ -29,13 +29,14 @@
 import           Control.Arrow              (left)
 import           Control.Concurrent         (forkIO, killThread, ThreadId)
 import           Control.Exception          (bracket)
-import           Control.Monad.Trans.Except (throwE )
+import           Control.Monad.Error.Class  (throwError )
 import           Data.Aeson
 import qualified Data.ByteString.Lazy       as BS
 import           Data.Char                  (chr, isPrint)
 import           Data.Foldable              (forM_)
 import           Data.Monoid                hiding (getLast)
 import           Data.Proxy
+import qualified Generics.SOP               as SOP
 import           GHC.Generics               (Generic)
 import qualified Network.HTTP.Client        as C
 import           Network.HTTP.Media
@@ -55,6 +56,7 @@
 import           Servant.API
 import           Servant.API.Internal.Test.ComprehensiveAPI
 import           Servant.Client
+import           Servant.Client.Generic
 import qualified Servant.Common.Req         as SCR
 import           Servant.Server
 import           Servant.Server.Experimental.Auth
@@ -69,6 +71,7 @@
     wrappedApiSpec
     basicAuthSpec
     genAuthSpec
+    genericClientSpec
 
 -- * test data types
 
@@ -108,6 +111,8 @@
             Get '[JSON] (String, Maybe Int, Bool, [(String, [Rational])])
   :<|> "headers" :> Get '[JSON] (Headers TestHeaders Bool)
   :<|> "deleteContentType" :> DeleteNoContent '[JSON] NoContent
+  :<|> "empty" :> EmptyAPI
+
 api :: Proxy Api
 api = Proxy
 
@@ -119,14 +124,15 @@
 getQueryParam   :: Maybe String -> SCR.ClientM Person
 getQueryParams  :: [String] -> SCR.ClientM [Person]
 getQueryFlag    :: Bool -> SCR.ClientM Bool
-getRawSuccess :: HTTP.Method 
+getRawSuccess :: HTTP.Method
   -> SCR.ClientM (Int, BS.ByteString, MediaType, [HTTP.Header], C.Response 
BS.ByteString)
-getRawFailure   :: HTTP.Method 
+getRawFailure   :: HTTP.Method
   -> SCR.ClientM (Int, BS.ByteString, MediaType, [HTTP.Header], C.Response 
BS.ByteString)
 getMultiple     :: String -> Maybe Int -> Bool -> [(String, [Rational])]
   -> SCR.ClientM (String, Maybe Int, Bool, [(String, [Rational])])
 getRespHeaders  :: SCR.ClientM (Headers TestHeaders Bool)
 getDeleteContentType :: SCR.ClientM NoContent
+
 getGet
   :<|> getDeleteEmpty
   :<|> getCapture
@@ -139,7 +145,8 @@
   :<|> getRawFailure
   :<|> getMultiple
   :<|> getRespHeaders
-  :<|> getDeleteContentType = client api
+  :<|> getDeleteContentType
+  :<|> EmptyClient = client api
 
 server :: Application
 server = serve api (
@@ -150,16 +157,16 @@
   :<|> return
   :<|> (\ name -> case name of
                    Just "alice" -> return alice
-                   Just n -> throwE $ ServantErr 400 (n ++ " not found") "" []
-                   Nothing -> throwE $ ServantErr 400 "missing parameter" "" 
[])
+                   Just n -> throwError $ ServantErr 400 (n ++ " not found") 
"" []
+                   Nothing -> throwError $ ServantErr 400 "missing parameter" 
"" [])
   :<|> (\ names -> return (zipWith Person names [0..]))
   :<|> return
-  :<|> (\ _request respond -> respond $ responseLBS HTTP.ok200 [] "rawSuccess")
-  :<|> (\ _request respond -> respond $ responseLBS HTTP.badRequest400 [] 
"rawFailure")
+  :<|> (Tagged $ \ _request respond -> respond $ responseLBS HTTP.ok200 [] 
"rawSuccess")
+  :<|> (Tagged $ \ _request respond -> respond $ responseLBS 
HTTP.badRequest400 [] "rawFailure")
   :<|> (\ a b c d -> return (a, b, c, d))
   :<|> (return $ addHeader 1729 $ addHeader "eg2" True)
   :<|> return NoContent
- )
+  :<|> emptyServer)
 
 
 type FailApi =
@@ -171,9 +178,9 @@
 
 failServer :: Application
 failServer = serve failApi (
-       (\ _request respond -> respond $ responseLBS HTTP.ok200 [] "")
-  :<|> (\ _capture _request respond -> respond $ responseLBS HTTP.ok200 
[("content-type", "application/json")] "")
-  :<|> (\_request respond -> respond $ responseLBS HTTP.ok200 
[("content-type", "fooooo")] "")
+       (Tagged $ \ _request respond -> respond $ responseLBS HTTP.ok200 [] "")
+  :<|> (\ _capture -> Tagged $ \_request respond -> respond $ responseLBS 
HTTP.ok200 [("content-type", "application/json")] "")
+  :<|> (Tagged $ \_request respond -> respond $ responseLBS HTTP.ok200 
[("content-type", "fooooo")] "")
  )
 
 -- * basic auth stuff
@@ -212,7 +219,7 @@
 genAuthHandler :: AuthHandler Request ()
 genAuthHandler =
   let handler req = case lookup "AuthHeader" (requestHeaders req) of
-        Nothing -> throwE (err401 { errBody = "Missing auth header" })
+        Nothing -> throwError (err401 { errBody = "Missing auth header" })
         Just _ -> return ()
   in mkAuthHandler handler
 
@@ -222,6 +229,53 @@
 genAuthServer :: Application
 genAuthServer = serveWithContext genAuthAPI genAuthServerContext (const 
(return alice))
 
+-- * generic client stuff
+
+type GenericClientAPI
+    = QueryParam "sqr" Int :> Get '[JSON] Int
+ :<|> Capture "foo" String :> NestedAPI1
+
+data GenericClient = GenericClient
+  { getSqr          :: Maybe Int -> SCR.ClientM Int
+  , mkNestedClient1 :: String -> NestedClient1
+  } deriving Generic
+instance SOP.Generic GenericClient
+instance (Client GenericClientAPI ~ client) => ClientLike client GenericClient
+
+type NestedAPI1
+    = QueryParam "int" Int :> NestedAPI2
+ :<|> QueryParam "id" Char :> Get '[JSON] Char
+
+data NestedClient1 = NestedClient1
+  { mkNestedClient2 :: Maybe Int -> NestedClient2
+  , idChar          :: Maybe Char -> SCR.ClientM Char
+  } deriving Generic
+instance SOP.Generic NestedClient1
+instance (Client NestedAPI1 ~ client) => ClientLike client NestedClient1
+
+type NestedAPI2
+    = "sum"  :> Capture "first" Int :> Capture "second" Int :> Get '[JSON] Int
+ :<|> "void" :> Post '[JSON] ()
+
+data NestedClient2 = NestedClient2
+  { getSum    :: Int -> Int -> SCR.ClientM Int
+  , doNothing :: SCR.ClientM ()
+  } deriving Generic
+instance SOP.Generic NestedClient2
+instance (Client NestedAPI2 ~ client) => ClientLike client NestedClient2
+
+genericClientServer :: Application
+genericClientServer = serve (Proxy :: Proxy GenericClientAPI) (
+       (\ mx -> case mx of
+                  Just x -> return (x*x)
+                  Nothing -> throwError $ ServantErr 400 "missing parameter" 
"" []
+       )
+  :<|> nestedServer1
+ )
+  where
+    nestedServer1 _str = nestedServer2 :<|> (maybe (throwError $ ServantErr 
400 "missing parameter" "" []) return)
+    nestedServer2 _int = (\ x y -> return (x + y)) :<|> return ()
+
 {-# NOINLINE manager #-}
 manager :: C.Manager
 manager = unsafePerformIO $ C.newManager C.defaultManagerSettings
@@ -298,7 +352,7 @@
 
 wrappedApiSpec :: Spec
 wrappedApiSpec = describe "error status codes" $ do
-  let serveW api = serve api $ throwE $ ServantErr 500 "error message" "" []
+  let serveW api = serve api $ throwError $ ServantErr 500 "error message" "" 
[]
   context "are correctly handled by the client" $
     let test :: (WrappedApi, String) -> Spec
         test (WrappedApi api, desc) =
@@ -322,7 +376,7 @@
         let (_ :<|> getDeleteEmpty :<|> _) = client api
         Left res <- runClientM getDeleteEmpty (ClientEnv manager baseUrl)
         case res of
-          FailureResponse (HTTP.Status 404 "Not Found") _ _ -> return ()
+          FailureResponse _ (HTTP.Status 404 "Not Found") _ _ -> return ()
           _ -> fail $ "expected 404 response, but got " <> show res
 
       it "reports DecodeFailure" $ \(_, baseUrl) -> do
@@ -392,6 +446,22 @@
       Left FailureResponse{..} <- runClientM (getProtected authRequest) 
(ClientEnv manager baseUrl)
       responseStatus `shouldBe` (HTTP.Status 401 "Unauthorized")
 
+genericClientSpec :: Spec
+genericClientSpec = beforeAll (startWaiApp genericClientServer) $ afterAll 
endWaiApp $ do
+  describe "Servant.Client.Generic" $ do
+
+    let GenericClient{..} = mkClient (client (Proxy :: Proxy GenericClientAPI))
+        NestedClient1{..} = mkNestedClient1 "example"
+        NestedClient2{..} = mkNestedClient2 (Just 42)
+
+    it "works for top-level client function" $ \(_, baseUrl) -> do
+      (left show <$> (runClientM (getSqr (Just 5)) (ClientEnv manager 
baseUrl))) `shouldReturn` Right 25
+
+    it "works for nested clients" $ \(_, baseUrl) -> do
+      (left show <$> (runClientM (idChar (Just 'c')) (ClientEnv manager 
baseUrl))) `shouldReturn` Right 'c'
+      (left show <$> (runClientM (getSum 3 4) (ClientEnv manager baseUrl))) 
`shouldReturn` Right 7
+      (left show <$> (runClientM doNothing (ClientEnv manager baseUrl))) 
`shouldReturn` Right ()
+
 -- * utils
 
 startWaiApp :: Application -> IO (ThreadId, BaseUrl)

++++++ servant-client.cabal ++++++
--- /var/tmp/diff_new_pack.ZDkX7K/_old  2017-08-31 20:59:17.775535825 +0200
+++ /var/tmp/diff_new_pack.ZDkX7K/_new  2017-08-31 20:59:17.779535264 +0200
@@ -1,5 +1,5 @@
 name:                servant-client
-version:             0.9.1.1
+version:             0.11
 x-revision:          1
 synopsis: automatical derivation of querying functions for servant webservices
 description:
@@ -14,7 +14,7 @@
 author:              Servant Contributors
 maintainer:          [email protected]
 copyright:           2014-2016 Zalora South East Asia Pte Ltd, Servant 
Contributors
-category:            Web
+category:            Servant Web
 build-type:          Simple
 cabal-version:       >=1.10
 tested-with:         GHC >= 7.8
@@ -31,31 +31,39 @@
 library
   exposed-modules:
     Servant.Client
+    Servant.Client.Generic
     Servant.Client.Experimental.Auth
     Servant.Common.BaseUrl
     Servant.Common.BasicAuth
     Servant.Common.Req
   build-depends:
-      base                  >= 4.7      && < 4.10
+      base                  >= 4.7      && < 4.11
     , base-compat           >= 0.9.1    && < 0.10
-    , aeson                 >= 0.7      && < 1.2
+    , aeson                 >= 0.7      && < 1.3
     , attoparsec            >= 0.12     && < 0.14
     , base64-bytestring     >= 1.0.0.1  && < 1.1
     , bytestring            >= 0.10     && < 0.11
     , exceptions            >= 0.8      && < 0.9
-    , http-api-data         >= 0.3      && < 0.4
+    , generics-sop          >= 0.1.0.0  && < 0.4
+    , http-api-data         >= 0.3.6    && < 0.4
     , http-client           >= 0.4.18.1 && < 0.6
     , http-client-tls       >= 0.2.2    && < 0.4
-    , http-media            >= 0.6.2    && < 0.7
+    , http-media            >= 0.6.2    && < 0.8
     , http-types            >= 0.8.6    && < 0.10
+    , monad-control         >= 1.0.0.4  && < 1.1
     , network-uri           >= 2.6      && < 2.7
     , safe                  >= 0.3.9    && < 0.4
-    , servant               == 0.9.*
+    , semigroupoids         >= 4.3      && < 5.3
+    , servant               == 0.11.*
     , string-conversions    >= 0.3      && < 0.5
     , text                  >= 1.2      && < 1.3
     , transformers          >= 0.3      && < 0.6
+    , transformers-base     >= 0.4.4    && < 0.5
     , transformers-compat   >= 0.4      && < 0.6
     , mtl
+  if !impl(ghc >= 8.0)
+    build-depends:
+        semigroups          >=0.16.2.2 && <0.19
   hs-source-dirs: src
   default-language: Haskell2010
   ghc-options: -Wall
@@ -74,10 +82,8 @@
     , Servant.Common.BaseUrlSpec
   build-depends:
       base == 4.*
-    , base-compat
-    , transformers
-    , transformers-compat
     , aeson
+    , base-compat
     , bytestring
     , deepseq
     , hspec == 2.*
@@ -86,11 +92,15 @@
     , http-media
     , http-types
     , HUnit
+    , mtl
     , network >= 2.6
     , QuickCheck >= 2.7
-    , servant == 0.9.*
+    , servant
     , servant-client
-    , servant-server == 0.9.*
+    , servant-server == 0.11.*
     , text
+    , transformers
+    , transformers-compat
     , wai
     , warp
+    , generics-sop


Reply via email to