packages feed

conduit-extra 1.1.1 → 1.1.2

raw patch · 4 files changed

+134/−3 lines, 4 filesdep +asyncdep +processdep +stmdep ~streaming-commonsPVP ok

version bump matches the API change (PVP)

Dependencies added: async, process, stm

Dependency ranges changed: streaming-commons

API changes (from Hackage documentation)

+ Data.Conduit.Process: instance (r ~ (), MonadIO m, i ~ ByteString) => InputSource (ConduitM i o m r)
+ Data.Conduit.Process: instance (r ~ (), MonadIO m, o ~ ByteString) => OutputSink (ConduitM i o m r)
+ Data.Conduit.Process: instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, i ~ ByteString) => InputSource (ConduitM i o m r, n r')
+ Data.Conduit.Process: instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, o ~ ByteString) => OutputSink (ConduitM i o m r, n r')
+ Data.Conduit.Process: sourceCmdWithConsumer :: MonadIO m => String -> Consumer ByteString m a -> m (ExitCode, a)
+ Data.Conduit.Process: sourceProcessWithConsumer :: MonadIO m => CreateProcess -> Consumer ByteString m a -> m (ExitCode, a)

Files

Data/Conduit/Binary.hs view
@@ -140,7 +140,9 @@ sinkHandle :: MonadIO m            => IO.Handle            -> Consumer S.ByteString m ()-sinkHandle h = awaitForever $ liftIO . S.hPut h+sinkHandle h = awaitForever $ \bs -> liftIO $ do+    S.hPut h bs+    IO.hFlush h  -- | An alternative to 'sinkHandle'. -- Instead of taking a pre-opened 'IO.Handle', it takes an action that opens
+ Data/Conduit/Process.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | A full tutorial for this module is available on FP School of Haskell:+-- <https://www.fpcomplete.com/user/snoyberg/library-documentation/data-conduit-process>.+--+-- Note that this is a very thin layer around the @Data.Streaming.Process@ module. In particular, it:+--+-- * Provides orphan instances for conduit+--+-- * Provides some useful helper functions+module Data.Conduit.Process+    ( -- * Functions+      sourceCmdWithConsumer+    , sourceProcessWithConsumer+      -- * Reexport+    , module Data.Streaming.Process+    ) where++import Data.Streaming.Process+import Data.Streaming.Process.Internal+import System.Exit (ExitCode (..))+import Control.Monad.IO.Class (MonadIO, liftIO)+import System.IO (hClose)+import Data.Conduit+import Data.Conduit.Binary (sourceHandle, sinkHandle)+import Data.ByteString (ByteString)++instance (r ~ (), MonadIO m, i ~ ByteString) => InputSource (ConduitM i o m r) where+    isStdStream = (\(Just h) -> return $ sinkHandle h, Just CreatePipe)+instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, i ~ ByteString) => InputSource (ConduitM i o m r, n r') where+    isStdStream = (\(Just h) -> return (sinkHandle h, liftIO $ hClose h), Just CreatePipe)++instance (r ~ (), MonadIO m, o ~ ByteString) => OutputSink (ConduitM i o m r) where+    osStdStream = (\(Just h) -> return $ sourceHandle h, Just CreatePipe)+instance (r ~ (), r' ~ (), MonadIO m, MonadIO n, o ~ ByteString) => OutputSink (ConduitM i o m r, n r') where+    osStdStream = (\(Just h) -> return (sourceHandle h, liftIO $ hClose h), Just CreatePipe)++-- | Given a @CreateProcess@, run the process, with its output being used as a+-- @Source@ to feed the provided @Consumer@. Once the process has completed,+-- return a tuple of the @ExitCode@ from the process and the output collected+-- from the @Consumer@.+--+-- Since 1.1.2+sourceProcessWithConsumer :: MonadIO m => CreateProcess -> Consumer ByteString m a -> m (ExitCode, a)+sourceProcessWithConsumer cp consumer = do+    (ClosedStream, (source, close), ClosedStream, cph) <- streamingProcess cp+    res <- source $$ consumer+    close+    ec <- waitForStreamingProcess cph+    return (ec, res)++-- | Like @sourceProcessWithConsumer@ but providing the command to be run as+-- a @String@.+--+-- Since 1.1.2+sourceCmdWithConsumer :: MonadIO m => String -> Consumer ByteString m a -> m (ExitCode, a)+sourceCmdWithConsumer cmd = sourceProcessWithConsumer (shell cmd)
conduit-extra.cabal view
@@ -1,5 +1,5 @@ Name:                conduit-extra-Version:             1.1.1+Version:             1.1.2 Synopsis:            Batteries included conduit: adapters for common libraries. Description:     The conduit package itself maintains relative small dependencies. The purpose of this package is to collect commonly used utility functions wrapping other library dependencies, without depending on heavier-weight dependencies. The basic idea is that this package should only depend on haskell-platform packages and conduit.@@ -24,6 +24,7 @@                        Data.Conduit.Lazy                        Data.Conduit.Network                        Data.Conduit.Network.UDP+                       Data.Conduit.Process                        Data.Conduit.Text                        Data.Conduit.Zlib   if !os(windows)@@ -46,8 +47,10 @@                      , filepath                      , network                  >= 2.3                      , primitive                >= 0.5+                     , process                      , resourcet                >= 1.1-                     , streaming-commons        >= 0.1.2+                     , stm+                     , streaming-commons        >= 0.1.4    ghc-options:     -Wall @@ -62,15 +65,20 @@                    , base                    , hspec >= 1.3 +                   , async                    , attoparsec                    , blaze-builder                    , bytestring                    , exceptions+                   , process                    , resourcet+                   , stm                    , text                    , transformers                    , transformers-base     ghc-options:     -Wall+    if os(windows)+        cpp-options: -DWINDOWS     other-modules:   Data.Conduit.AttoparsecSpec                      Data.Conduit.BinarySpec                      Data.Conduit.BlazeSpec@@ -78,6 +86,7 @@                      Data.Conduit.FilesystemSpec                      Data.Conduit.LazySpec                      Data.Conduit.NetworkSpec+                     Data.Conduit.ProcessSpec                      Data.Conduit.TextSpec                      Data.Conduit.ZlibSpec 
+ test/Data/Conduit/ProcessSpec.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE CPP #-}+module Data.Conduit.ProcessSpec (spec, main) where++import Test.Hspec+import Test.Hspec.QuickCheck (prop)+import Data.Conduit+import qualified Data.Conduit.List as CL+import Data.Conduit.Process+import Control.Concurrent.Async (concurrently)+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString as S+import System.Exit+import Control.Concurrent (threadDelay)++main :: IO ()+main = hspec spec++spec :: Spec+spec = describe "Data.Conduit.Process" $ do+#ifndef WINDOWS+    prop "cat" $ \wss -> do+        let lbs = L.fromChunks $ map S.pack wss+        ((sink, closeStdin), source, Inherited, cph) <- streamingProcess (shell "cat")+        ((), bss) <- concurrently+            (do+                mapM_ yield (L.toChunks lbs) $$ sink+                closeStdin)+            (source $$ CL.consume)+        L.fromChunks bss `shouldBe` lbs+        ec <- waitForStreamingProcess cph+        ec `shouldBe` ExitSuccess++    it "closed stream" $ do+        (ClosedStream, source, Inherited, cph) <- streamingProcess (shell "cat")+        bss <- source $$ CL.consume+        bss `shouldBe` []++        ec <- waitForStreamingProcess cph+        ec `shouldBe` ExitSuccess++    it "handles sub-process exit code" $ do+        (sourceCmdWithConsumer "exit 0" CL.sinkNull)+                `shouldReturn` (ExitSuccess, ())+        (sourceCmdWithConsumer "exit 11" CL.sinkNull)+                `shouldReturn` (ExitFailure 11, ())+        (sourceCmdWithConsumer "exit 12" CL.sinkNull)+                `shouldReturn` (ExitFailure 12, ())+#endif+    it "blocking vs non-blocking" $ do+        (ClosedStream, ClosedStream, ClosedStream, cph) <- streamingProcess (shell "sleep 1")++        mec1 <- getStreamingProcessExitCode cph+        mec1 `shouldBe` Nothing++        threadDelay 1500000++        mec2 <- getStreamingProcessExitCode cph+        mec2 `shouldBe` Just ExitSuccess++        ec <- waitForStreamingProcess cph+        ec `shouldBe` ExitSuccess