git.iko.soy/typeable/http-api-data
on master help sign in
Use quickcheck-instances, nats and void for compat
94210bcOleg Grenrus
http-api-data.cabal+13−7
@@ -55,14 +55,20 @@ library
55 -- other-dependencies
55 -- other-dependencies
56 build-depends:
56 build-depends:
57 attoparsec >= 0.13.2.2 && < 0.14
57 attoparsec >= 0.13.2.2 && < 0.14
58− , attoparsec-iso8601 >= 1.0.0.0 && < 1.1
58+ , attoparsec-iso8601 >= 1.0.1.0 && < 1.1
59+ , base-compat >= 0.10.5 && < 0.11
59 , cookie >= 0.4.3 && < 0.4.5
60 , cookie >= 0.4.3 && < 0.4.5
60 , hashable >= 1.2.7.0 && < 1.3
61 , hashable >= 1.2.7.0 && < 1.3
61− , http-types >= 0.12.1 && < 0.13
62+ , http-types >= 0.12.2 && < 0.13
62 , time-locale-compat >= 0.1.1.5 && < 0.2
63 , time-locale-compat >= 0.1.1.5 && < 0.2
63 , unordered-containers >= 0.2.9.0 && < 0.3
64 , unordered-containers >= 0.2.9.0 && < 0.3
64 , uuid-types >= 1.0.3 && <1.1
65 , uuid-types >= 1.0.3 && <1.1
65
66
67+ if !impl(ghc >= 7.10)
68+ build-depends:
69+ nats >= 1.1.2 && < 1.2,
70+ void >= 0.7.2 && < 0.8
71+
66 if !impl(ghc >= 8.0)
72 if !impl(ghc >= 8.0)
67 build-depends: semigroups >= 0.18.5 && < 0.19
73 build-depends: semigroups >= 0.18.5 && < 0.19
68
74
@@ -88,21 +94,21 @@ test-suite spec
88 hs-source-dirs: test
94 hs-source-dirs: test
89 ghc-options: -Wall
95 ghc-options: -Wall
90 default-language: Haskell2010
96 default-language: Haskell2010
91− build-tool-depends: hspec-discover:hspec-discover >= 2.5.5 && <2.6
97+ build-tool-depends: hspec-discover:hspec-discover >= 2.6.0 && <2.7
92 -- inherited depndencies
98 -- inherited depndencies
93 build-depends:
99 build-depends:
94 base
100 base
95 , bytestring
101 , bytestring
96− , unordered-containers
102+ , cookie
97 , http-api-data
103 , http-api-data
104+ , nats
98 , text
105 , text
99 , time
106 , time
100− , bytestring
107+ , unordered-containers
101 , uuid-types
108 , uuid-types
102− , cookie
103
109
104 build-depends: HUnit >= 1.6.0.0 && <1.7
110 build-depends: HUnit >= 1.6.0.0 && <1.7
105− , hspec >= 2.5.5 && <2.6
111+ , hspec >= 2.6.0 && <2.7
106 , QuickCheck >= 2.11.3 && <2.13
112 , QuickCheck >= 2.11.3 && <2.13
107 , quickcheck-instances >= 0.3.19 && <0.4
113 , quickcheck-instances >= 0.3.19 && <0.4
108
114
src/Web/Internal/FormUrlEncoded.hs+2−11
@@ -17,11 +17,8 @@
17#include "overlapping-compat.h"
17#include "overlapping-compat.h"
18module Web.Internal.FormUrlEncoded where
18module Web.Internal.FormUrlEncoded where
19
19
20−#if __GLASGOW_HASKELL__ < 710
20+import Prelude ()
21−import Control.Applicative
21+import Prelude.Compat
22−import Data.Traversable
23−#endif
24−
25
22
26import Control.Arrow ((***))
23import Control.Arrow ((***))
27import Control.Monad ((<=<))
24import Control.Monad ((<=<))
@@ -52,10 +49,8 @@ import Data.Proxy
52import Data.Time
49import Data.Time
53import Data.Word
50import Data.Word
54
51
55−#if MIN_VERSION_base(4,8,0)
56import Data.Void
52import Data.Void
57import Numeric.Natural
53import Numeric.Natural
58−#endif
59
54
60import GHC.Exts (Constraint, IsList (..))
55import GHC.Exts (Constraint, IsList (..))
61import GHC.Generics
56import GHC.Generics
@@ -128,10 +123,8 @@ instance ToFormKey a => ToFormKey (Dual a) where toFormKey = toFormKey . getD
128instance ToFormKey a => ToFormKey (Sum a) where toFormKey = toFormKey . getSum
123instance ToFormKey a => ToFormKey (Sum a) where toFormKey = toFormKey . getSum
129instance ToFormKey a => ToFormKey (Product a) where toFormKey = toFormKey . getProduct
124instance ToFormKey a => ToFormKey (Product a) where toFormKey = toFormKey . getProduct
130
125
131−#if MIN_VERSION_base(4,8,0)
132instance ToFormKey Void where toFormKey = toQueryParam
126instance ToFormKey Void where toFormKey = toQueryParam
133instance ToFormKey Natural where toFormKey = toQueryParam
127instance ToFormKey Natural where toFormKey = toQueryParam
134−#endif
135
128
136-- | Typeclass for types that can be parsed from keys of a 'Form'. This is the reverse of 'ToFormKey'.
129-- | Typeclass for types that can be parsed from keys of a 'Form'. This is the reverse of 'ToFormKey'.
137class FromFormKey k where
130class FromFormKey k where
@@ -175,10 +168,8 @@ instance FromFormKey a => FromFormKey (Dual a) where parseFormKey = fmap Dual
175instance FromFormKey a => FromFormKey (Sum a) where parseFormKey = fmap Sum . parseFormKey
168instance FromFormKey a => FromFormKey (Sum a) where parseFormKey = fmap Sum . parseFormKey
176instance FromFormKey a => FromFormKey (Product a) where parseFormKey = fmap Product . parseFormKey
169instance FromFormKey a => FromFormKey (Product a) where parseFormKey = fmap Product . parseFormKey
177
170
178−#if MIN_VERSION_base(4,8,0)
179instance FromFormKey Void where parseFormKey = parseQueryParam
171instance FromFormKey Void where parseFormKey = parseQueryParam
180instance FromFormKey Natural where parseFormKey = parseQueryParam
172instance FromFormKey Natural where parseFormKey = parseQueryParam
181−#endif
182
173
183-- | The contents of a form, not yet URL-encoded.
174-- | The contents of a form, not yet URL-encoded.
184--
175--
src/Web/Internal/HttpApiData.hs+5−15
@@ -13,11 +13,8 @@
13-- such as URL pieces, headers and query parameters.
13-- such as URL pieces, headers and query parameters.
14module Web.Internal.HttpApiData where
14module Web.Internal.HttpApiData where
15
15
16−#if __GLASGOW_HASKELL__ < 710
16+import Prelude ()
17−import Control.Applicative
17+import Prelude.Compat
18−import Data.Foldable (Foldable)
19−import Data.Traversable (Traversable (traverse))
20−#endif
21
18
22import Control.Arrow (left, (&&&))
19import Control.Arrow (left, (&&&))
23import Control.Monad ((<=<))
20import Control.Monad ((<=<))
@@ -33,22 +30,19 @@ import Data.Word
33
30
34import Data.Text (Text)
31import Data.Text (Text)
35import qualified Data.Text as T
32import qualified Data.Text as T
36−import Data.Text.Encoding (decodeUtf8With, decodeUtf8', encodeUtf8)
33+import Data.Text.Encoding (decodeUtf8', decodeUtf8With,
34+ encodeUtf8)
37import Data.Text.Encoding.Error (lenientDecode)
35import Data.Text.Encoding.Error (lenientDecode)
38import qualified Data.Text.Lazy as L
36import qualified Data.Text.Lazy as L
39import Data.Text.Read (Reader, decimal, rational,
37import Data.Text.Read (Reader, decimal, rational,
40 signed)
38 signed)
41
39
42import Data.Time
40import Data.Time
43−#if __GLASGOW_HASKELL__ < 710
44import Data.Time.Locale.Compat
41import Data.Time.Locale.Compat
45−#endif
46import Data.Version
42import Data.Version
47
43
48−#if MIN_VERSION_base(4,8,0)
49import Data.Void
44import Data.Void
50import Numeric.Natural
45import Numeric.Natural
51−#endif
52
46
53import Text.ParserCombinators.ReadP (readP_to_S)
47import Text.ParserCombinators.ReadP (readP_to_S)
54import Text.Read (readMaybe)
48import Text.Read (readMaybe)
@@ -432,10 +426,8 @@ instance ToHttpApiData Version where
432 toUrlPiece = T.pack . showVersion
426 toUrlPiece = T.pack . showVersion
433 toEncodedUrlPiece = unsafeToEncodedUrlPiece
427 toEncodedUrlPiece = unsafeToEncodedUrlPiece
434
428
435−#if MIN_VERSION_base(4,8,0)
436instance ToHttpApiData Void where toUrlPiece = absurd
429instance ToHttpApiData Void where toUrlPiece = absurd
437instance ToHttpApiData Natural where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece
430instance ToHttpApiData Natural where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece
438−#endif
439
431
440instance ToHttpApiData Bool where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece
432instance ToHttpApiData Bool where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece
441instance ToHttpApiData Ordering where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece
433instance ToHttpApiData Ordering where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece
@@ -566,7 +558,7 @@ instance FromHttpApiData Char where
566 parseUrlPiece s =
558 parseUrlPiece s =
567 case T.uncons s of
559 case T.uncons s of
568 Just (c, s') | T.null s' -> pure c
560 Just (c, s') | T.null s' -> pure c
569− _ -> defaultParseError s
561+ _ -> defaultParseError s
570
562
571-- |
563-- |
572-- >>> showVersion <$> parseUrlPiece "1.2.3"
564-- >>> showVersion <$> parseUrlPiece "1.2.3"
@@ -577,7 +569,6 @@ instance FromHttpApiData Version where
577 ((x, ""):_) -> pure x
569 ((x, ""):_) -> pure x
578 _ -> defaultParseError s
570 _ -> defaultParseError s
579
571
580−#if MIN_VERSION_base(4,8,0)
581-- | Parsing a @'Void'@ value is always an error, considering @'Void'@ as a data type with no constructors.
572-- | Parsing a @'Void'@ value is always an error, considering @'Void'@ as a data type with no constructors.
582instance FromHttpApiData Void where
573instance FromHttpApiData Void where
583 parseUrlPiece _ = Left "Void cannot be parsed!"
574 parseUrlPiece _ = Left "Void cannot be parsed!"
@@ -588,7 +579,6 @@ instance FromHttpApiData Natural where
588 if n < 0
579 if n < 0
589 then Left ("underflow: " <> s <> " (should be a non-negative integer)")
580 then Left ("underflow: " <> s <> " (should be a non-negative integer)")
590 else Right (fromInteger n)
581 else Right (fromInteger n)
591−#endif
592
582
593instance FromHttpApiData Bool where parseUrlPiece = parseBoundedUrlPiece
583instance FromHttpApiData Bool where parseUrlPiece = parseBoundedUrlPiece
594instance FromHttpApiData Ordering where parseUrlPiece = parseBoundedUrlPiece
584instance FromHttpApiData Ordering where parseUrlPiece = parseBoundedUrlPiece
test/Web/Internal/HttpApiDataSpec.hs+6−35
@@ -19,9 +19,7 @@ import Web.Cookie (SetCookie, defaultSetCookie, setCookieName, setCookieValue)
19
19
20import Data.Proxy
20import Data.Proxy
21
21
22−#if MIN_VERSION_base(4,8,0)
23import Numeric.Natural
22import Numeric.Natural
24−#endif
25
23
26import Test.Hspec
24import Test.Hspec
27import Test.Hspec.QuickCheck(prop)
25import Test.Hspec.QuickCheck(prop)
@@ -80,13 +78,13 @@ spec = do
80 checkUrlPiece (Proxy :: Proxy T.Text) "Text.Strict"
78 checkUrlPiece (Proxy :: Proxy T.Text) "Text.Strict"
81 checkUrlPiece (Proxy :: Proxy L.Text) "Text.Lazy"
79 checkUrlPiece (Proxy :: Proxy L.Text) "Text.Lazy"
82 checkUrlPiece (Proxy :: Proxy Day) "Day"
80 checkUrlPiece (Proxy :: Proxy Day) "Day"
83− checkUrlPiece' timeOfDayGen "TimeOfDay"
81+ checkUrlPiece (Proxy :: Proxy TimeOfDay) "TimeOfDay"
84− checkUrlPiece' localTimeGen "LocalTime"
82+ checkUrlPiece (Proxy :: Proxy LocalTime) "LocalTime"
85− checkUrlPiece' zonedTimeGen "ZonedTime"
83+ checkUrlPiece (Proxy :: Proxy ZonedTime) "ZonedTime"
86− checkUrlPiece' utcTimeGen "UTCTime"
84+ checkUrlPiece (Proxy :: Proxy UTCTime) "UTCTime"
87− checkUrlPiece' nominalDiffTimeGen "NominalDiffTime"
85+ checkUrlPiece (Proxy :: Proxy NominalDiffTime) "NominalDiffTime"
88 checkUrlPiece (Proxy :: Proxy Version) "Version"
86 checkUrlPiece (Proxy :: Proxy Version) "Version"
89− checkUrlPiece' uuidGen "UUID"
87+ checkUrlPiece (Proxy :: Proxy UUID.UUID) "UUID"
90 checkUrlPiece' setCookieGen "Cookie"
88 checkUrlPiece' setCookieGen "Cookie"
91
89
92 checkUrlPiece (Proxy :: Proxy F.Uni) "Uni"
90 checkUrlPiece (Proxy :: Proxy F.Uni) "Uni"
@@ -102,9 +100,7 @@ spec = do
102 checkUrlPiece (Proxy :: Proxy (Either Integer T.Text)) "Either Integer Text"
100 checkUrlPiece (Proxy :: Proxy (Either Integer T.Text)) "Either Integer Text"
103 checkUrlPieceI (Proxy :: Proxy (Either Version Day)) "Either Version Day"
101 checkUrlPieceI (Proxy :: Proxy (Either Version Day)) "Either Version Day"
104
102
105−#if MIN_VERSION_base(4,8,0)
106 checkUrlPiece (Proxy :: Proxy Natural) "Natural"
103 checkUrlPiece (Proxy :: Proxy Natural) "Natural"
107−#endif
108
104
109 it "bad integers are rejected" $ do
105 it "bad integers are rejected" $ do
110 parseUrlPieceMaybe (T.pack "123hello") `shouldBe` (Nothing :: Maybe Int)
106 parseUrlPieceMaybe (T.pack "123hello") `shouldBe` (Nothing :: Maybe Int)
@@ -116,31 +112,6 @@ spec = do
116 it "invalid utf8 is handled" $ do
112 it "invalid utf8 is handled" $ do
117 parseHeaderMaybe (BS.pack [128]) `shouldBe` (Nothing :: Maybe T.Text)
113 parseHeaderMaybe (BS.pack [128]) `shouldBe` (Nothing :: Maybe T.Text)
118
114
119−
120−uuidGen :: Gen UUID.UUID
121−uuidGen = UUID.fromWords <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
122−
123−-- TODO: this generators don't generate full range items
124−localTimeGen :: Gen LocalTime
125−localTimeGen = LocalTime <$> arbitrary <*> timeOfDayGen
126−
127−timeOfDayGen :: Gen TimeOfDay
128−timeOfDayGen = TimeOfDay
129− <$> choose (0, 23)
130− <*> choose (0, 59)
131− <*> fmap (\x -> 0.1 * fromInteger x) (choose (0, 600))
132−
133−zonedTimeGen :: Gen ZonedTime
134−zonedTimeGen = ZonedTime
135− <$> localTimeGen -- Note: not arbitrary!
136− <*> liftA3 TimeZone arbitrary arbitrary (vectorOf 3 (elements ['A'..'Z']))
137−
138−utcTimeGen :: Gen UTCTime
139−utcTimeGen = UTCTime <$> arbitrary <*> fmap fromInteger (choose (0, 86400))
140−
141−nominalDiffTimeGen :: Gen NominalDiffTime
142−nominalDiffTimeGen = fromInteger <$> arbitrary
143−
144setCookieGen :: Gen SetCookie
115setCookieGen :: Gen SetCookie
145setCookieGen = do
116setCookieGen = do
146 n <- TE.encodeUtf8 . T.pack . filter isAlphaNum <$> arbitrary
117 n <- TE.encodeUtf8 . T.pack . filter isAlphaNum <$> arbitrary