conduit-combinators 1.0.8.3 → 1.1.0
raw patch · 7 files changed
+33/−185 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.Conduit.Combinators.Stream: sourceHandleS :: (MonadIO m, MonoFoldable a, IOData a) => Handle -> StreamProducer m a
- Conduit: sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()
+ Conduit: sinkFile :: MonadResource m => FilePath -> Consumer ByteString m ()
- Conduit: sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()
+ Conduit: sinkHandle :: MonadIO m => Handle -> Consumer ByteString m ()
- Conduit: sinkIOHandle :: (MonadResource m, IOData a) => IO Handle -> Consumer a m ()
+ Conduit: sinkIOHandle :: MonadResource m => IO Handle -> Consumer ByteString m ()
- Conduit: sourceFile :: (MonadResource m, IOData a, MonoFoldable a) => FilePath -> Producer m a
+ Conduit: sourceFile :: MonadResource m => FilePath -> Producer m ByteString
- Conduit: sourceHandle :: (MonadIO m, IOData a, MonoFoldable a) => Handle -> Producer m a
+ Conduit: sourceHandle :: MonadIO m => Handle -> Producer m ByteString
- Conduit: sourceIOHandle :: (MonadResource m, IOData a, MonoFoldable a) => IO Handle -> Producer m a
+ Conduit: sourceIOHandle :: MonadResource m => IO Handle -> Producer m ByteString
- Conduit: stderrC :: (MonadIO m, IOData a) => Consumer a m ()
+ Conduit: stderrC :: MonadIO m => Consumer ByteString m ()
- Conduit: stdinC :: (MonadIO m, IOData a, MonoFoldable a) => Producer m a
+ Conduit: stdinC :: MonadIO m => Producer m ByteString
- Conduit: stdoutC :: (MonadIO m, IOData a) => Consumer a m ()
+ Conduit: stdoutC :: MonadIO m => Consumer ByteString m ()
- Data.Conduit.Combinators: sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()
+ Data.Conduit.Combinators: sinkFile :: MonadResource m => FilePath -> Consumer ByteString m ()
- Data.Conduit.Combinators: sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()
+ Data.Conduit.Combinators: sinkHandle :: MonadIO m => Handle -> Consumer ByteString m ()
- Data.Conduit.Combinators: sinkIOHandle :: (MonadResource m, IOData a) => IO Handle -> Consumer a m ()
+ Data.Conduit.Combinators: sinkIOHandle :: MonadResource m => IO Handle -> Consumer ByteString m ()
- Data.Conduit.Combinators: sourceFile :: (MonadResource m, IOData a, MonoFoldable a) => FilePath -> Producer m a
+ Data.Conduit.Combinators: sourceFile :: MonadResource m => FilePath -> Producer m ByteString
- Data.Conduit.Combinators: sourceHandle :: (MonadIO m, IOData a, MonoFoldable a) => Handle -> Producer m a
+ Data.Conduit.Combinators: sourceHandle :: MonadIO m => Handle -> Producer m ByteString
- Data.Conduit.Combinators: sourceIOHandle :: (MonadResource m, IOData a, MonoFoldable a) => IO Handle -> Producer m a
+ Data.Conduit.Combinators: sourceIOHandle :: MonadResource m => IO Handle -> Producer m ByteString
- Data.Conduit.Combinators: stderr :: (MonadIO m, IOData a) => Consumer a m ()
+ Data.Conduit.Combinators: stderr :: MonadIO m => Consumer ByteString m ()
- Data.Conduit.Combinators: stdin :: (MonadIO m, IOData a, MonoFoldable a) => Producer m a
+ Data.Conduit.Combinators: stdin :: MonadIO m => Producer m ByteString
- Data.Conduit.Combinators: stdout :: (MonadIO m, IOData a) => Consumer a m ()
+ Data.Conduit.Combinators: stdout :: MonadIO m => Consumer ByteString m ()
Files
- ChangeLog.md +6/−0
- Data/Conduit/Combinators.hs +5/−73
- Data/Conduit/Combinators/Stream.hs +0/−15
- Data/Conduit/Combinators/Unqualified.hs +9/−77
- conduit-combinators.cabal +1/−1
- test/Spec.hs +12/−11
- test/StreamSpec.hs +0/−8
ChangeLog.md view
@@ -1,3 +1,9 @@+# 1.1.0++* Don't generalize I/O functions to `IOData`, instead specialize to+ `ByteString`. See:+ http://www.snoyman.com/blog/2016/12/beware-of-readfile#real-world-failures+ # 1.0.8.3 * Fix version bounds for chunked-data/mono-traversable combos
Data/Conduit/Combinators.hs view
@@ -214,10 +214,11 @@ import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Resource (MonadResource, MonadThrow) import Data.Conduit+import Data.Conduit.Binary (sourceFile, sourceHandle, sourceIOHandle,+ sinkFile, sinkHandle, sinkIOHandle) import qualified Data.Conduit.Filesystem as CF import Data.Conduit.Internal (ConduitM (..), Pipe (..)) import qualified Data.Conduit.List as CL-import Data.IOData import Data.Maybe (fromMaybe, isNothing, isJust) import Data.Monoid (Monoid (..)) import Data.MonoTraversable@@ -414,17 +415,6 @@ -> Producer m a INLINE_RULE(replicateM, n m, CL.replicateM n m) --- | Read all data from the given file.------ This function automatically opens and closes the file handle, and ensures--- exception safety via @MonadResource@. It works for all instances of @IOData@,--- including @ByteString@ and @Text@.------ Since 1.0.0-sourceFile :: (MonadResource m, IOData a, MonoFoldable a) => FilePath -> Producer m a-sourceFile fp = sourceIOHandle (SIO.openFile fp SIO.ReadMode)-{-# INLINE sourceFile #-}- -- | 'sourceFile' specialized to 'ByteString' to help with type -- inference. --@@ -433,40 +423,12 @@ sourceFileBS = sourceFile {-# INLINE sourceFileBS #-} --- | Read all data from the given @Handle@.------ Does not close the @Handle@ at any point.------ Subject to fusion------ Since 1.0.0-sourceHandle, sourceHandleC :: (MonadIO m, IOData a, MonoFoldable a) => Handle -> Producer m a-sourceHandleC h =- loop- where- loop = do- x <- liftIO (hGetChunk h)- if onull x- then return ()- else yield x >> loop-{-# INLINEABLE sourceHandleC #-}-STREAMING(sourceHandle, sourceHandleC, sourceHandleS, h)---- | Open a @Handle@ using the given function and stream data from it.------ Automatically closes the file at completion.------ Since 1.0.0-sourceIOHandle :: (MonadResource m, IOData a, MonoFoldable a) => SIO.IO Handle -> Producer m a-sourceIOHandle alloc = bracketP alloc SIO.hClose sourceHandle-{-# INLINE sourceIOHandle #-}- -- | @sourceHandle@ applied to @stdin@. -- -- Subject to fusion -- -- Since 1.0.0-stdin :: (MonadIO m, IOData a, MonoFoldable a) => Producer m a+stdin :: MonadIO m => Producer m ByteString INLINE_RULE0(stdin, sourceHandle SIO.stdin) -- | Create an infinite stream of random values, seeding from the system random@@ -1321,17 +1283,6 @@ -> Consumer mono m w INLINE_RULE(foldMapME, f, CL.foldM (ofoldlM (\accum e -> mappend accum `liftM` f e)) mempty) --- | Write all data to the given file.------ This function automatically opens and closes the file handle, and ensures--- exception safety via @MonadResource@. It works for all instances of @IOData@,--- including @ByteString@ and @Text@.------ Since 1.0.0-sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()-sinkFile fp = sinkIOHandle (SIO.openFile fp SIO.WriteMode)-{-# INLINE sinkFile #-}- -- | 'sinkFile' specialized to 'ByteString' to help with type -- inference. --@@ -1353,7 +1304,7 @@ -- Subject to fusion -- -- Since 1.0.0-stdout :: (MonadIO m, IOData a) => Consumer a m ()+stdout :: MonadIO m => Consumer ByteString m () INLINE_RULE0(stdout, sinkHandle SIO.stdout) -- | @sinkHandle@ applied to @stderr@.@@ -1361,27 +1312,8 @@ -- Subject to fusion -- -- Since 1.0.0-stderr :: (MonadIO m, IOData a) => Consumer a m ()+stderr :: MonadIO m => Consumer ByteString m () INLINE_RULE0(stderr, sinkHandle SIO.stderr)---- | Write all data to the given @Handle@.------ Does not close the @Handle@ at any point.------ Subject to fusion------ Since 1.0.0-sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()-INLINE_RULE(sinkHandle, h, CL.mapM_ (hPut h))---- | Open a @Handle@ using the given function and stream data to it.------ Automatically closes the file at completion.------ Since 1.0.0-sinkIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Consumer a m ()-sinkIOHandle alloc = bracketP alloc SIO.hClose sinkHandle-{-# INLINE sinkIOHandle #-} -- | Apply a transformation to all values in a stream. --
Data/Conduit/Combinators/Stream.hs view
@@ -12,7 +12,6 @@ ( yieldManyS , repeatMS , repeatWhileMS- , sourceHandleS , foldl1S , allS , anyS@@ -43,12 +42,10 @@ import Control.Monad (liftM) import Control.Monad.Base (MonadBase (liftBase))-import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Primitive (PrimMonad) import Data.Builder import Data.Conduit.Internal.Fusion import Data.Conduit.Internal.List.Stream (foldS)-import Data.IOData import Data.Maybe (isNothing, isJust) import Data.MonoTraversable #if ! MIN_VERSION_base(4,8,0)@@ -59,7 +56,6 @@ import qualified Data.Vector.Generic as V import qualified Data.Vector.Generic.Mutable as VM import Prelude-import System.IO (Handle) #if MIN_VERSION_mono_traversable(1,0,0) import Data.Sequences (LazySequence (..))@@ -101,17 +97,6 @@ then Emit () x else Stop () {-# INLINE repeatWhileMS #-}--sourceHandleS :: (MonadIO m, MonoFoldable a, IOData a) => Handle -> StreamProducer m a-sourceHandleS h _ =- Stream step (return ())- where- step () = do- x <- liftIO (hGetChunk h)- return $ if onull x- then Stop ()- else Emit () x-{-# INLINE sourceHandleS #-} foldl1S :: Monad m => (a -> a -> a)
Data/Conduit/Combinators/Unqualified.hs view
@@ -24,10 +24,10 @@ , replicateMC -- *** I\/O- , sourceFile+ , CC.sourceFile , CC.sourceFileBS- , sourceHandle- , sourceIOHandle+ , CC.sourceHandle+ , CC.sourceIOHandle , stdinC -- *** Random numbers@@ -109,10 +109,10 @@ , foldMapMCE -- *** I\/O- , sinkFile+ , CC.sinkFile , CC.sinkFileBS- , sinkHandle- , sinkIOHandle+ , CC.sinkHandle+ , CC.sinkIOHandle , printC , stdoutC , stderrC@@ -187,19 +187,11 @@ import Data.Builder import qualified Data.NonNull as NonNull import qualified Data.Traversable-#if ! MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))-#else-import Prelude ((<$>))-#endif import Control.Monad.Base (MonadBase (..)) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Primitive (PrimMonad, PrimState) import Control.Monad.Trans.Resource (MonadResource, MonadThrow) import Data.Conduit-import qualified Data.Conduit.List as CL-import Data.IOData-import Data.Maybe (fromMaybe) import Data.Monoid (Monoid (..)) import Data.MonoTraversable import qualified Data.Sequences as Seq@@ -209,8 +201,6 @@ Ord (..), Functor (..), Either (..), Enum, Show, Char, FilePath) import Data.Word (Word8)-import qualified Prelude-import System.IO (Handle) import qualified System.IO as SIO import Data.ByteString (ByteString) import Data.Text (Text)@@ -324,39 +314,10 @@ replicateMC = CC.replicateM {-# INLINE replicateMC #-} --- | Read all data from the given file.------ This function automatically opens and closes the file handle, and ensures--- exception safety via @MonadResource. It works for all instances of @IOData@,--- including @ByteString@ and @Text@.------ Since 1.0.0-sourceFile :: (MonadResource m, IOData a, MonoFoldable a) => FilePath -> Producer m a-sourceFile = CC.sourceFile-{-# INLINE sourceFile #-}---- | Read all data from the given @Handle@.------ Does not close the @Handle@ at any point.------ Since 1.0.0-sourceHandle :: (MonadIO m, IOData a, MonoFoldable a) => Handle -> Producer m a-sourceHandle = CC.sourceHandle-{-# INLINE sourceHandle #-}---- | Open a @Handle@ using the given function and stream data from it.------ Automatically closes the file at completion.------ Since 1.0.0-sourceIOHandle :: (MonadResource m, IOData a, MonoFoldable a) => SIO.IO Handle -> Producer m a-sourceIOHandle = CC.sourceIOHandle-{-# INLINE sourceIOHandle #-}- -- | @sourceHandle@ applied to @stdin@. -- -- Since 1.0.0-stdinC :: (MonadIO m, IOData a, MonoFoldable a) => Producer m a+stdinC :: MonadIO m => Producer m ByteString stdinC = CC.stdin {-# INLINE stdinC #-} @@ -1007,35 +968,6 @@ foldMapMCE = CC.foldMapME {-# INLINE foldMapMCE #-} --- | Write all data to the given file.------ This function automatically opens and closes the file handle, and ensures--- exception safety via @MonadResource. It works for all instances of @IOData@,--- including @ByteString@ and @Text@.------ Since 1.0.0-sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()-sinkFile = CC.sinkFile-{-# INLINE sinkFile #-}---- | Write all data to the given @Handle@.------ Does not close the @Handle@ at any point.------ Since 1.0.0-sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()-sinkHandle = CC.sinkHandle-{-# INLINE sinkHandle #-}---- | Open a @Handle@ using the given function and stream data to it.------ Automatically closes the file at completion.------ Since 1.0.0-sinkIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Consumer a m ()-sinkIOHandle = CC.sinkIOHandle-{-# INLINE sinkIOHandle #-}- -- | Print all incoming values to stdout. -- -- Since 1.0.0@@ -1046,14 +978,14 @@ -- | @sinkHandle@ applied to @stdout@. -- -- Since 1.0.0-stdoutC :: (MonadIO m, IOData a) => Consumer a m ()+stdoutC :: MonadIO m => Consumer ByteString m () stdoutC = CC.stdout {-# INLINE stdoutC #-} -- | @sinkHandle@ applied to @stderr@. -- -- Since 1.0.0-stderrC :: (MonadIO m, IOData a) => Consumer a m ()+stderrC :: MonadIO m => Consumer ByteString m () stderrC = CC.stderr {-# INLINE stderrC #-}
conduit-combinators.cabal view
@@ -1,5 +1,5 @@ name: conduit-combinators-version: 1.0.8.3+version: 1.1.0 synopsis: Commonly used conduit functions, for both chunked and unchunked data description: Provides a replacement for Data.Conduit.List, as well as a convenient Conduit module. homepage: https://github.com/snoyberg/mono-traversable
test/Spec.hs view
@@ -15,6 +15,7 @@ import Test.Hspec.QuickCheck import qualified Data.Text as T import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TL import Data.IORef import qualified Data.Vector as V import qualified Data.Vector.Unboxed as VU@@ -112,20 +113,20 @@ fp = "tmp" writeFile fp contents res <- runResourceT $ sourceFile fp $$ sinkLazy- res `shouldBe` TL.pack contents+ res `shouldBe` TL.encodeUtf8 (TL.pack contents) it "sourceHandle" $ do let contents = concat $ replicate 10000 $ "this is some content\n" fp = "tmp" writeFile fp contents res <- IO.withBinaryFile "tmp" IO.ReadMode $ \h -> sourceHandle h $$ sinkLazy- res `shouldBe` TL.pack contents+ res `shouldBe` TL.encodeUtf8 (TL.pack contents) it "sourceIOHandle" $ do let contents = concat $ replicate 10000 $ "this is some content\n" fp = "tmp" writeFile fp contents let open = IO.openBinaryFile "tmp" IO.ReadMode res <- runResourceT $ sourceIOHandle open $$ sinkLazy- res `shouldBe` TL.pack contents+ res `shouldBe` TL.encodeUtf8 (TL.pack contents) prop "stdin" $ \(S.pack -> content) -> do S.writeFile "tmp" content IO.withBinaryFile "tmp" IO.ReadMode $ \h -> do@@ -326,23 +327,23 @@ res = runIdentity $ src $$ foldMapMCE (return . return) in res `shouldBe` [1..10] it "sinkFile" $ do- let contents = concat $ replicate 1000 $ "this is some content\n"+ let contents = mconcat $ replicate 1000 $ "this is some content\n" fp = "tmp" runResourceT $ yield contents $$ sinkFile fp- res <- readFile fp+ res <- S.readFile fp res `shouldBe` contents it "sinkHandle" $ do- let contents = concat $ replicate 1000 $ "this is some content\n"+ let contents = mconcat $ replicate 1000 $ "this is some content\n" fp = "tmp" IO.withBinaryFile "tmp" IO.WriteMode $ \h -> yield contents $$ sinkHandle h- res <- readFile fp+ res <- S.readFile fp res `shouldBe` contents it "sinkIOHandle" $ do- let contents = concat $ replicate 1000 $ "this is some content\n"+ let contents = mconcat $ replicate 1000 $ "this is some content\n" fp = "tmp" open = IO.openBinaryFile "tmp" IO.WriteMode runResourceT $ yield contents $$ sinkIOHandle open- res <- readFile fp+ res <- S.readFile fp res `shouldBe` contents prop "print" $ \vals -> do let expected = Prelude.unlines $ map showInt vals@@ -350,11 +351,11 @@ actual `shouldBe` expected prop "stdout" $ \ (vals :: [String]) -> do let expected = concat vals- (actual, ()) <- hCapture [IO.stdout] $ yieldMany vals $$ stdoutC+ (actual, ()) <- hCapture [IO.stdout] $ yieldMany (map T.pack vals) $$ encodeUtf8C =$ stdoutC actual `shouldBe` expected prop "stderr" $ \ (vals :: [String]) -> do let expected = concat vals- (actual, ()) <- hCapture [IO.stderr] $ yieldMany vals $$ stderrC+ (actual, ()) <- hCapture [IO.stderr] $ yieldMany (map T.pack vals) $$ encodeUtf8C =$ stderrC actual `shouldBe` expected prop "map" $ \input -> runIdentity (yieldMany input $$ mapC succChar =$ sinkList)
test/StreamSpec.hs view
@@ -42,14 +42,6 @@ spec :: Spec spec = do- it "sourceHandleS works" $ do- let contents = Prelude.concat $ Prelude.replicate 10000 $ "this is some content\n"- fp = "tmp"- IO.writeFile fp contents- (res, ()) <- IO.withBinaryFile "tmp" IO.ReadMode $ \h ->- evalStream $ sourceHandleS h emptyStream- (TL.concat res) `shouldBe` TL.pack contents- removeFile "tmp" describe "Comparing list function to" $ do qit "yieldMany" $ \(mono :: Seq Int) ->