cassava-conduit 0.6.0 → 0.6.1
raw patch · 3 files changed
+39/−6 lines, 3 filesdep ~bytestringPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: bytestring
API changes (from Hackage documentation)
+ Data.Csv.Conduit: fromCsvStreamErrorNoThrow :: (Monad m, FromRecord a) => DecodeOptions -> HasHeader -> ConduitT ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()
+ Data.Csv.Conduit: fromNamedCsvStreamErrorNoThrow :: (Monad m, FromNamedRecord a) => DecodeOptions -> ConduitT ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()
Files
- CHANGELOG.md +5/−1
- cassava-conduit.cabal +4/−4
- src/Data/Csv/Conduit.hs +30/−1
CHANGELOG.md view
@@ -1,4 +1,8 @@-# 0.6.x+# 0.6.1++- Add `fromCsvStreamErrorNoThrow` and `fromNamedCsvStreamErrorNoThrow`, functions that also put halting errors on the conduit instead of throwing in `MonadError`.++# 0.6.0 - `streamParser` and functions using it would swallow certain runaway errors. This is fixed.
cassava-conduit.cabal view
@@ -1,5 +1,5 @@ name: cassava-conduit-version: 0.6.0+version: 0.6.1 license: BSD3 license-file: etc/LICENCE.md author: Dom De Re@@ -12,7 +12,7 @@ PRs welcome. homepage: https://github.com/domdere/cassava-conduit bug-reports: https://github.com/domdere/cassava-conduit/issues-cabal-version: >= 1.18+cabal-version: 1.24 build-type: Simple tested-with: GHC == 8.0.2 , GHC == 8.2.2@@ -33,7 +33,7 @@ , containers , array , bifunctors >= 4.2 && < 6- , bytestring == 0.10.*+ , bytestring == 0.11.* , cassava == 0.5.* , conduit == 1.3.* , mtl == 2.2.*@@ -58,7 +58,7 @@ Test.Data.Csv.Conduit build-depends: base >= 4 && < 5- , bytestring == 0.10.*+ , bytestring == 0.11.* , cassava == 0.5.* , conduit == 1.3.* , QuickCheck == 2.12.*
src/Data/Csv/Conduit.hs view
@@ -20,7 +20,9 @@ , fromNamedCsv , fromNamedCsvLiftError , fromCsvStreamError+ , fromCsvStreamErrorNoThrow , fromNamedCsvStreamError+ , fromNamedCsvStreamErrorNoThrow , toCsv ) where @@ -90,18 +92,30 @@ fromNamedCsvLiftError f opts = {-# SCC fromNamedCsv_p #-} terminatingStreamHeaderParser f $ decodeByNameWith opts -- |--- Same as `fromCsv` but allows for errors to be handled in the pipeline instead+-- Same as 'fromCsv' but allows for errors to be handled in the pipeline instead -- fromCsvStreamError :: (FromRecord a, MonadError e m) => DecodeOptions -> HasHeader -> (CsvStreamHaltParseError -> e) -> ConduitT BS.ByteString (Either CsvStreamRecordParseError a) m () fromCsvStreamError opts h f = {-# SCC fromCsvStreamError_p #-} streamParser f $ decodeWith opts h -- |+-- Same as 'fromCsvStreamError' but allows for halting errors to be handled by the pipeline as well.+--+fromCsvStreamErrorNoThrow :: (Monad m, FromRecord a) => DecodeOptions -> HasHeader -> ConduitT BS.ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()+fromCsvStreamErrorNoThrow opts h = {-# SCC fromCsvStreamErrorNoThrow_p #-} streamParserNoThrow $ decodeWith opts h++-- | -- Like `fromNamedCsvStream` but allows for errors to be handled in the pipeline itself. -- fromNamedCsvStreamError :: (FromNamedRecord a, MonadError e m) => DecodeOptions -> (CsvStreamHaltParseError -> e) -> ConduitT BS.ByteString (Either CsvStreamRecordParseError a) m () fromNamedCsvStreamError opts f = {-# SCC fromCsvStreamError_p #-} streamHeaderParser f $ decodeByNameWith opts -- |+-- Like `fromNamedCsvStreamErrorNoThrow` but allows for errors to be handled in the pipeline itself.+--+fromNamedCsvStreamErrorNoThrow :: (Monad m, FromNamedRecord a) => DecodeOptions -> ConduitT BS.ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()+fromNamedCsvStreamErrorNoThrow opts = {-# SCC fromCsvStreamErrorNoThrow_p #-} streamHeaderParserNoThrow $ decodeByNameWith opts++-- | -- Streams from csv to text, does not create headers... -- toCsv :: (Monad m, ToRecord a) => EncodeOptions -> ConduitT a BS.ByteString m ()@@ -114,6 +128,11 @@ streamHeaderParser f (PartialH p) = {-# SCC streamHeaderParser_PartialH_p #-} await >>= maybe (return ()) (streamHeaderParser f . p) streamHeaderParser f (DoneH _ p) = {-# SCC streamHeaderParser_DoneH_p #-} streamParser f p +streamHeaderParserNoThrow :: (Monad m) => HeaderParser (Parser a) -> ConduitT BS.ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()+streamHeaderParserNoThrow (FailH rest errMsg) = {-# SCC streamHeaderParserNoThrow_FailH_p #-} yield $ Left $ Left $ HaltingCsvParseError rest (T.pack errMsg)+streamHeaderParserNoThrow (PartialH p) = {-# SCC streamHeaderParserNoThrow_PartialH_p #-} await >>= maybe (return ()) (streamHeaderParserNoThrow . p)+streamHeaderParserNoThrow (DoneH _ p) = {-# SCC streamHeaderParserNoThrow_DoneH_p #-} streamParserNoThrow p+ streamParser :: (MonadError e m) => (CsvStreamHaltParseError -> e) -> Parser a -> ConduitT BS.ByteString (Either CsvStreamRecordParseError a) m () streamParser f (Fail rest errMsg) = {-# SCC streamParser_Fail_p #-} lift . throwError . f $ HaltingCsvParseError rest (T.pack errMsg) streamParser f (Many rs p) = {-# SCC streamParser_Many_p #-} do@@ -123,6 +142,16 @@ more <- await streamParser f . p $ fromMaybe BS.empty more streamParser _ (Done rs) = {-# SCC streamParser_Done_p #-} mapM_ (yield . first (CsvStreamRecordParseError . T.pack)) rs++streamParserNoThrow :: (Monad m) => Parser a -> ConduitT BS.ByteString (Either (Either CsvStreamHaltParseError CsvStreamRecordParseError) a) m ()+streamParserNoThrow (Fail rest errMsg) = {-# SCC streamParserNoThrow_Fail_p #-} yield $ Left $ Left $ HaltingCsvParseError rest (T.pack errMsg)+streamParserNoThrow (Many rs p) = {-# SCC streamParserNoThrow_Many_p #-} do+ -- send the results down the stream..+ mapM_ (yield . first (Right . CsvStreamRecordParseError . T.pack)) rs+ -- wait for more..+ more <- await+ streamParserNoThrow . p $ fromMaybe BS.empty more+streamParserNoThrow (Done rs) = {-# SCC streamParserNoThrow_Done_p #-} mapM_ (yield . first (Right . CsvStreamRecordParseError . T.pack)) rs terminatingStreamHeaderParser :: (Monad m, MonadError e m)