cassava 0.5.3.1 → 0.5.3.2
raw patch · 4 files changed
+45/−21 lines, 4 filesdep ~basedep ~containersdep ~hashablePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, containers, hashable
API changes (from Hackage documentation)
Files
- CHANGES.md +7/−0
- cassava.cabal +6/−10
- src/Data/Csv/Parser.hs +14/−11
- tests/UnitTests.hs +18/−0
CHANGES.md view
@@ -1,3 +1,10 @@+## Version 0.5.3.2++ * Proper exception on hanging doublequote ([PR #222](https://github.com/haskell-hvr/cassava/pull/222)).+ * Allow latest `hashable`.+ * Build tested with GHC 8.0 - 9.10.1.+ * Functionality tested with GHC 8.4 - 9.10.1.+ ## Version 0.5.3.1 * Remove support for GHC 7.
cassava.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 Name: cassava-Version: 0.5.3.1+Version: 0.5.3.2 Synopsis: A CSV parsing and encoding library Description: { @@ -43,9 +43,9 @@ CHANGES.md, README.md Tested-with:- GHC == 9.10.0+ GHC == 9.10.1 GHC == 9.8.2- GHC == 9.6.5+ GHC == 9.6.6 GHC == 9.4.8 GHC == 9.2.8 GHC == 9.0.2@@ -68,7 +68,6 @@ BangPatterns CPP DataKinds- DataKinds DefaultSignatures DeriveFunctor FlexibleContexts@@ -77,7 +76,6 @@ MultiParamTypeClasses OverloadedStrings PolyKinds- PolyKinds Rank2Types ScopedTypeVariables TypeOperators@@ -106,7 +104,7 @@ , bytestring >= 0.10.4 && < 0.13 , containers >= 0.4.2 && < 0.8 , deepseq >= 1.1 && < 1.6- , hashable < 1.5+ , hashable < 2 , scientific >= 0.3.4.7 && < 0.4 , text < 2.2 , text-short == 0.1.*@@ -138,7 +136,7 @@ Main-is: UnitTests.hs -- dependencies with version constraints inherited via lib:cassava Build-depends: attoparsec- , base+ , base >= 4.11 && < 5 , bytestring , cassava , hashable@@ -160,12 +158,10 @@ -Wall -- https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#Recommendationsforforward-compatibility -Wcompat+ -Wcpp-undef -Wnoncanonical-monad-instances if impl(ghc >= 8.8) ghc-options: -Wno-star-is-type else ghc-options: -Wnoncanonical-monadfail-instances-- if impl(ghc >= 8.2)- ghc-options: -Wcpp-undef
src/Data/Csv/Parser.hs view
@@ -149,17 +149,20 @@ escapedField :: AL.Parser S.ByteString escapedField = do _ <- dquote- -- The scan state is 'True' if the previous character was a double- -- quote. We need to drop a trailing double quote left by scan.- s <- S.init <$> (A.scan False $ \s c -> if c == doubleQuote- then Just (not s)- else if s then Nothing- else Just False)- if doubleQuote `S.elem` s- then case Z.parse unescape s of- Right r -> return r- Left err -> fail err- else return s+ -- The scan state is 'True' if the previous character was a double quote.+ s' <- A.scan False $ \s c -> if c == doubleQuote+ then Just (not s)+ else if s then Nothing+ else Just False+ -- We need to drop a trailing double quote left by scan.+ if S.null s'+ then fail "trailing double quote"+ else let s = S.init s'+ in if doubleQuote `S.elem` s+ then case Z.parse unescape s of+ Right r -> return r+ Left err -> fail err+ else return s unescapedField :: Word8 -> AL.Parser S.ByteString unescapedField !delim = A.takeWhile (\ c -> c /= doubleQuote &&
tests/UnitTests.hs view
@@ -17,6 +17,7 @@ import qualified Data.Text.Lazy as LT import qualified Data.Vector as V import qualified Data.Foldable as F+import Data.List (isPrefixOf) import Data.Word import Numeric.Natural import GHC.Generics (Generic)@@ -48,6 +49,14 @@ " input: " ++ show (BL8.unpack input) ++ "\n" ++ "parse error: " ++ err +decodeFailsWith :: BL.ByteString -> String -> Assertion+decodeFailsWith input expected = case decode NoHeader input of+ Right r -> assertFailure $ "input: " ++ show (BL8.unpack input) ++ "\n" +++ "retuned: " ++ show (r :: (V.Vector (V.Vector B.ByteString))) ++ "\n" +++ "whereas should have failed with " <> expected+ Left err -> assertBool ("got " <> err <> "\ninstead of " <> expected)+ $ ("parse error ("++expected++")") `isPrefixOf` err+ encodesAs :: [[B.ByteString]] -> BL.ByteString -> Assertion encodesAs input expected = encode (map V.fromList input) @?= expected@@ -158,6 +167,11 @@ [ testGroup "decode" $ map streamingDecodeTest decodeTests , testGroup "decodeWith" $ map streamingDecodeWithTest decodeWithTests ]+ , testGroup "failing"+ [ testCase "escapedMalformed0" $+ "baz,\"" `decodeFailsWith` "Failed reading: trailing double quote"+ ]+ ] where rfc4180Input = BL8.pack $@@ -178,6 +192,10 @@ [["a", "b", "c"], ["d", "e", "f"]]) , ("leadingSpace", " a, b, c\n", [[" a", " b", " c"]]) , ("rfc4180", rfc4180Input, rfc4180Output)+ , ("escapedDoubleQuotes"+ , "\"x,y\",z\nbaz,\"bar\nfoo,\""+ , [["x,y", "z"], ["baz", "bar\nfoo,"]]+ ) ] decodeWithTests = [ ("tab-delim", defDec { decDelimiter = 9 }, "1\t2", [["1", "2"]])