csv-conduit 0.1 → 0.2
raw patch · 3 files changed
+131/−41 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.CSV.Conduit: class CSVeable s r
- Data.CSV.Conduit: instance (CSVeable s (Row s'), Ord s', IsString s) => CSVeable s (MapRow s')
- Data.CSV.Conduit: instance CSVeable ByteString (Row ByteString)
- Data.CSV.Conduit: instance CSVeable ByteString (Row Text)
- Data.CSV.Conduit: instance CSVeable Text (Row Text)
+ Data.CSV.Conduit: class CSV s r
+ Data.CSV.Conduit: instance (CSV s (Row s'), Ord s', IsString s) => CSV s (MapRow s')
+ Data.CSV.Conduit: instance CSV ByteString (Row ByteString)
+ Data.CSV.Conduit: instance CSV ByteString (Row Text)
+ Data.CSV.Conduit: instance CSV Text (Row Text)
+ Data.CSV.Conduit: runResourceT :: MonadBaseControl IO m => ResourceT m a -> m a
+ Data.CSV.Conduit: transformCSV :: (MonadResource m, CSV s a, CSV s' b) => CSVSettings -> Source m s -> Conduit a m b -> Sink s' m () -> m ()
- Data.CSV.Conduit: fromCSV :: (CSVeable s r, MonadResource m) => CSVSettings -> Conduit r m s
+ Data.CSV.Conduit: fromCSV :: (CSV s r, MonadResource m) => CSVSettings -> Conduit r m s
- Data.CSV.Conduit: intoCSV :: (CSVeable s r, MonadResource m) => CSVSettings -> Conduit s m r
+ Data.CSV.Conduit: intoCSV :: (CSV s r, MonadResource m) => CSVSettings -> Conduit s m r
- Data.CSV.Conduit: mapCSVFile :: (MonadIO m, MonadUnsafeIO m, MonadThrow m, MonadBaseControl IO m, CSVeable ByteString a, CSVeable ByteString b) => CSVSettings -> (a -> b) -> FilePath -> FilePath -> m ()
+ Data.CSV.Conduit: mapCSVFile :: (MonadResource m, CSV ByteString a, CSV ByteString b) => CSVSettings -> (a -> [b]) -> FilePath -> FilePath -> m ()
- Data.CSV.Conduit: readCSVFile :: (MonadUnsafeIO m, MonadThrow m, MonadBaseControl IO m, MonadIO m, CSVeable ByteString a) => CSVSettings -> FilePath -> m [a]
+ Data.CSV.Conduit: readCSVFile :: (MonadResource m, CSV ByteString a) => CSVSettings -> FilePath -> m [a]
- Data.CSV.Conduit: rowToStr :: CSVeable s r => CSVSettings -> r -> s
+ Data.CSV.Conduit: rowToStr :: CSV s r => CSVSettings -> r -> s
Files
- README.markdown +29/−11
- csv-conduit.cabal +2/−2
- src/Data/CSV/Conduit.hs +100/−28
README.markdown view
@@ -47,29 +47,47 @@ ### Usage Examples -#### Example 1: Basic Operation +#### Example #1: Basics Using Convenience API+ {-# LANGUAGE OverloadedStrings #-} - import Data.Conduit.Text+ import Data.Conduit import Data.Conduit.Binary+ import Data.Conduit.List as CL+ import Data.CSV.Conduit+ + -- Just reverse te columns+ myProcessor :: Conduit (Row Text) m (Row Text)+ myProcessor = CL.map reverse+ + test :: IO ()+ test = runResourceT $ + transformCSV defCSVSettings + (sourceFile "input.csv") + myProcessor+ (sinkFile "output.csv")+++#### Example #2: Basics Using Conduit API++ {-# LANGUAGE OverloadedStrings #-}+ import Data.Conduit+ import Data.Conduit.Binary import Data.CSV.Conduit + myProcessor :: Conduit (Row Text) m (Row Text)+ myProcessor = undefined+ -- Let's simply stream from a file, parse the CSV, reserialize it -- and push back into another file. test :: IO () test = runResourceT $ sourceFile "test/BigFile.csv" $= - decode utf8 $=- (intoCSV defCSVSettings - :: forall m. MonadResource m => Conduit Text m (MapRow Text)) $= - fromCSV defCSVSettings $=- encode utf8 $$+ intoCSV defCSVSettings $=+ myProcessor $=+ fromCSV defCSVSettings $$ sinkFile "test/BigFileOut.csv"---and we are done. -
csv-conduit.cabal view
@@ -1,12 +1,12 @@ Name: csv-conduit-Version: 0.1+Version: 0.2 Synopsis: A flexible, fast, conduit-based CSV parser library for Haskell. Homepage: http://github.com/ozataman/csv-conduit License: BSD3 License-file: LICENSE Author: Ozgun Ataman Maintainer: Ozgun Ataman <ozataman@gmail.com>-Category: Data+Category: Data, Conduit Build-type: Simple Cabal-version: >=1.6 Description:
src/Data/CSV/Conduit.hs view
@@ -6,14 +6,21 @@ {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} module Data.CSV.Conduit- ( CSVeable (..)+ ( + + -- * Fundamental Types+ CSV (..) , CSVSettings (..) , defCSVSettings , MapRow , Row -- * Convenience Functions , readCSVFile+ , transformCSV , mapCSVFile+ + -- * Re-exported For Convenience+ , runResourceT ) where -------------------------------------------------------------------------------@@ -50,40 +57,67 @@ ---------------------------------------------------------------------------------- | Represents types 'r' that can be converted from an underlying--- stream of type 's'.+-- | Represents types 'r' that are CSV-like and can be converted+-- to/from an underlying stream of type 's'. ----- Example processing using MapRow Text isntance:+-- +-- Example #1: Basics Using Convenience API+-- +-- @+-- import Data.Conduit+-- import Data.Conduit.Binary+-- import Data.Conduit.List as CL+-- import Data.CSV.Conduit --+-- myProcessor :: Conduit (Row Text) m (Row Text)+-- myProcessor = CL.map reverse+-- +-- test = runResourceT $ +-- transformCSV defCSVSettings +-- (sourceFile "input.csv") +-- myProcessor+-- (sinkFile "output.csv") -- @--- test :: IO ()+--+--+-- Example #2: Basics Using Conduit API+-- +-- @+-- import Data.Conduit+-- import Data.Conduit.Binary+-- import Data.CSV.Conduit+--+-- myProcessor :: Conduit (Row Text) m (Row Text)+-- myProcessor = undefined+-- -- test = runResourceT $ -- sourceFile "test/BigFile.csv" $= --- decode utf8 $= -- intoCSV defCSVSettings $=--- myMapRowProcessingConduit $=--- fromCSV defCSVSettings $=--- encode utf8 $$+-- myProcessor $=+-- fromCSV defCSVSettings $$ -- sinkFile "test/BigFileOut.csv" -- @-class CSVeable s r where+class CSV s r where ----------------------------------------------------------------------------- -- | Convert a CSV row into strict ByteString equivalent. rowToStr :: CSVSettings -> r -> s ------------------------------------------------------------------------------ -- | Turn a stream of 's' into a stream of CSV row type+ -- | Turn a stream of 's' into a stream of CSV row type. An example+ -- would be parsing a ByteString stream as rows of 'MapRow' 'Text'. intoCSV :: MonadResource m => CSVSettings -> Conduit s m r ------------------------------------------------------------------------------ -- | Turn a stream of CSV row type back into a stream of 's'+ -- | Turn a stream of CSV row type back into a stream of 's'. An+ -- example would be rendering a stream of 'Row' 'ByteString' rows as+ -- 'Text'. fromCSV :: MonadResource m => CSVSettings -> Conduit r m s ------------------------------------------------------------------------------ -- | 'Row' instance using 'ByteString'-instance CSVeable ByteString (Row ByteString) where+instance CSV ByteString (Row ByteString) where rowToStr s !r = let sep = B.pack [c2w (csvOutputColSep s)] @@ -99,7 +133,7 @@ ------------------------------------------------------------------------------ -- | 'Row' instance using 'Text'-instance CSVeable Text (Row Text) where+instance CSV Text (Row Text) where rowToStr s !r = let sep = T.pack [(csvOutputColSep s)] @@ -115,7 +149,7 @@ ------------------------------------------------------------------------------- -- | 'Row' instance using 'Text' based on 'ByteString' stream-instance CSVeable ByteString (Row Text) where+instance CSV ByteString (Row Text) where rowToStr s r = T.encodeUtf8 $ rowToStr s r intoCSV set = intoCSV set =$= C.map (map T.decodeUtf8) fromCSV set = fromCSV set =$= C.map T.encodeUtf8@@ -151,7 +185,7 @@ ------------------------------------------------------------------------------- -- | Generic 'MapRow' instance; any stream type with a 'Row' instance -- automatically gets a 'MapRow' instance.-instance (CSVeable s (Row s'), Ord s', IsString s) => CSVeable s (MapRow s') where+instance (CSV s (Row s'), Ord s', IsString s) => CSV s (MapRow s') where rowToStr s r = rowToStr s . M.elems $ r intoCSV set = intoCSVMap set fromCSV set = fromCSVMap set@@ -188,32 +222,70 @@ ---------------------------------------------------------------------------------- | Read the entire contents of a CSV file into memory-readCSVFile set fp = runResourceT $ sourceFile fp $= intoCSV set $$ C.consume+-- | Read the entire contents of a CSV file into memory.+--+-- An easy way to run this function would be 'runResourceT' after+-- feeding it all the arguments.+readCSVFile + :: (MonadResource m, CSV ByteString a) + => CSVSettings + -> FilePath + -- ^ Input file+ -> m [a]+readCSVFile set fp = sourceFile fp $= intoCSV set $$ C.consume ---------------------------------------------------------------------------------- | Map over the rows of a CSV file. Don't be scared by the type--- signature, this can just run in IO.+-- | Map over the rows of a CSV file. Provided for convenience for+-- historical reasons.+--+-- An easy way to run this function would be 'runResourceT' after+-- feeding it all the arguments. mapCSVFile - :: (MonadIO m, MonadUnsafeIO m, MonadThrow m, - MonadBaseControl IO m, CSVeable ByteString a, CSVeable ByteString b) + :: (MonadResource m, CSV ByteString a, CSV ByteString b) => CSVSettings -- ^ Settings to use both for input and output- -> (a -> b) + -> (a -> [b]) -- ^ A mapping function -> FilePath -- ^ Input file -> FilePath -- ^ Output file -> m ()-mapCSVFile set f fi fo = runResourceT $- sourceFile fi $=+mapCSVFile set f fi fo = + transformCSV set (sourceFile fi) (C.concatMap f) (sinkFile fo)+++-------------------------------------------------------------------------------+-- | General purpose CSV transformer. Apply a list-like processing+-- function from 'Data.Conduit.List' to the rows of a CSV stream. You+-- need to provide a stream data source, a transformer and a stream+-- data sink.+--+-- An easy way to run this function would be 'runResourceT' after+-- feeding it all the arguments.+--+-- Example - map a function over the rows of a CSV file:+-- +-- > transformCSV set (sourceFile inFile) (C.map f) (sinkFile outFile)+transformCSV + :: (MonadResource m, CSV s a, CSV s' b) + => CSVSettings + -- ^ Settings to be used for input and output+ -> Source m s+ -- ^ A raw stream data source. Ex: 'sourceFile inFile'+ -> Conduit a m b+ -- ^ A transforming conduit+ -> Sink s' m ()+ -- ^ A raw stream data sink. Ex: 'sinkFile outFile'+ -> m ()+transformCSV set source c sink = + source $= intoCSV set $=- C.map f $=+ c $= fromCSV set $$- sinkFile fo-+ sink+ ----------------- -- Simple Test --