Hello community, here is the log from the commit of package ghc-conduit for openSUSE:Factory checked in at 2015-12-09 19:52:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-conduit (Old) and /work/SRC/openSUSE:Factory/.ghc-conduit.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ghc-conduit" Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-conduit/ghc-conduit.changes 2015-10-25 19:13:35.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.ghc-conduit.new/ghc-conduit.changes 2015-12-09 22:16:58.000000000 +0100 @@ -1,0 +2,7 @@ +Mon Dec 7 10:32:58 UTC 2015 - mimi.vx@gmail.com + +- update to 1.2.6 +* sourceToList +* Canonicalise Monad instances + +------------------------------------------------------------------- Old: ---- conduit-1.2.5.1.tar.gz New: ---- conduit-1.2.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-conduit.spec ++++++ --- /var/tmp/diff_new_pack.JHZROl/_old 2015-12-09 22:16:59.000000000 +0100 +++ /var/tmp/diff_new_pack.JHZROl/_new 2015-12-09 22:16:59.000000000 +0100 @@ -19,7 +19,7 @@ %global pkg_name conduit Name: ghc-conduit -Version: 1.2.5.1 +Version: 1.2.6 Release: 0 Summary: Streaming data processing library License: MIT ++++++ conduit-1.2.5.1.tar.gz -> conduit-1.2.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/Data/Conduit/Internal/Conduit.hs new/conduit-1.2.6/Data/Conduit/Internal/Conduit.hs --- old/conduit-1.2.5.1/Data/Conduit/Internal/Conduit.hs 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/Data/Conduit/Internal/Conduit.hs 2015-11-29 14:39:04.000000000 +0100 @@ -74,7 +74,9 @@ , zipSources , zipSourcesApp , zipConduitApp + , mergeSource , passthroughSink + , sourceToList , fuseBoth , fuseBothMaybe , fuseUpstream @@ -123,13 +125,13 @@ fmap f (ConduitM c) = ConduitM $ \rest -> c (rest . f) instance Applicative (ConduitM i o m) where - pure = return + pure x = ConduitM ($ x) {-# INLINE pure #-} (<*>) = ap {-# INLINE (<*>) #-} instance Monad (ConduitM i o m) where - return x = ConduitM ($ x) + return = pure ConduitM f >>= g = ConduitM $ \h -> f $ \a -> unConduitM (g a) h instance MonadThrow m => MonadThrow (ConduitM i o m) where @@ -664,6 +666,25 @@ newResumableConduit :: Monad m => Conduit i m o -> ResumableConduit i m o newResumableConduit (ConduitM c) = ResumableConduit (c Done) (return ()) + +-- | Merge a @Source@ into a @Conduit@. +-- The new conduit will stop processing once either source or upstream have been exhausted. +mergeSource + :: Monad m + => Source m i + -> Conduit a m (i, a) +mergeSource = loop . newResumableSource + where + loop :: Monad m => ResumableSource m i -> Conduit a m (i, a) + loop src0 = await >>= maybe (lift $ closeResumableSource src0) go + where + go a = do + (src1, mi) <- lift $ src0 $$++ await + case mi of + Nothing -> lift $ closeResumableSource src1 + Just i -> yield (i, a) >> loop src1 + + -- | Turn a @Sink@ into a @Conduit@ in the following way: -- -- * All input passed to the @Sink@ is yielded downstream. @@ -700,6 +721,26 @@ go [] (next x) in go [] (sink0 Done) +-- | Convert a @Source@ into a list. The basic functionality can be explained as: +-- +-- > sourceToList src = src $$ Data.Conduit.List.consume +-- +-- However, @sourceToList@ is able to produce its results lazily, which cannot +-- be done when running a conduit pipeline in general. Unlike the +-- @Data.Conduit.Lazy@ module, this function performs no unsafe I\/O +-- operations, and therefore can only be as lazily as the underlying monad. +-- +-- Since 1.2.6 +sourceToList :: Monad m => Source m a -> m [a] +sourceToList = + go . flip unConduitM Done + where + go (Done _) = return [] + go (HaveOutput src _ x) = liftM (x:) (go src) + go (PipeM msrc) = msrc >>= go + go (NeedInput _ c) = go (c ()) + go (Leftover p _) = go p + -- Define fixity of all our operators infixr 0 $$ infixl 1 $= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/Data/Conduit/Internal/Pipe.hs new/conduit-1.2.6/Data/Conduit/Internal/Pipe.hs --- old/conduit-1.2.5.1/Data/Conduit/Internal/Pipe.hs 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/Data/Conduit/Internal/Pipe.hs 2015-11-29 14:39:04.000000000 +0100 @@ -108,13 +108,13 @@ {-# INLINE fmap #-} instance Monad m => Applicative (Pipe l i o u m) where - pure = return + pure = Done {-# INLINE pure #-} (<*>) = ap {-# INLINE (<*>) #-} instance Monad m => Monad (Pipe l i o u m) where - return = Done + return = pure {-# INLINE return #-} HaveOutput p c o >>= fp = HaveOutput (p >>= fp) c o diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/Data/Conduit.hs new/conduit-1.2.6/Data/Conduit.hs --- old/conduit-1.2.5.1/Data/Conduit.hs 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/Data/Conduit.hs 2015-11-29 14:39:04.000000000 +0100 @@ -52,7 +52,9 @@ , mapOutput , mapOutputMaybe , mapInput + , mergeSource , passthroughSink + , sourceToList -- * Connect-and-resume , ResumableSource diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/changelog.md new/conduit-1.2.6/changelog.md --- old/conduit-1.2.5.1/changelog.md 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/changelog.md 2015-11-29 14:39:04.000000000 +0100 @@ -1,3 +1,8 @@ +## 1.2.6 + +* `sourceToList` +* Canonicalise Monad instances [#237](https://github.com/snoyberg/conduit/pull/237) + ## 1.2.5 * mapAccum and mapAccumM should be strict in their state [#218](https://github.com/snoyberg/conduit/issues/218) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/conduit.cabal new/conduit-1.2.6/conduit.cabal --- old/conduit-1.2.5.1/conduit.cabal 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/conduit.cabal 2015-11-29 14:39:04.000000000 +0100 @@ -1,5 +1,5 @@ Name: conduit -Version: 1.2.5.1 +Version: 1.2.6 Synopsis: Streaming data processing library. description: Hackage documentation generation is not reliable. For up to date documentation, please see: http://www.stackage.org/package/conduit. @@ -27,7 +27,7 @@ Data.Conduit.Internal.List.Stream other-modules: Data.Conduit.Internal.Pipe Data.Conduit.Internal.Conduit - Build-depends: base >= 4.3 && < 5 + Build-depends: base >= 4.5 && < 5 , resourcet >= 1.1 && < 1.2 , exceptions >= 0.6 , lifted-base >= 0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/conduit-1.2.5.1/test/main.hs new/conduit-1.2.6/test/main.hs --- old/conduit-1.2.5.1/test/main.hs 2015-10-18 07:20:06.000000000 +0200 +++ new/conduit-1.2.6/test/main.hs 2015-11-29 14:39:04.000000000 +0100 @@ -12,6 +12,7 @@ import qualified Data.Conduit.Internal as CI import qualified Data.Conduit.List as CL import Data.Typeable (Typeable) +import Control.Exception (throw) import Control.Monad.Trans.Resource as C (runResourceT) import Data.Maybe (fromMaybe,catMaybes,fromJust) import qualified Data.List as DL @@ -730,6 +731,103 @@ res <- C.yield 10 C.$$ C.awaitForever (C.toProducer . src) C.=$ (C.toConsumer sink >>= C.yield) C.=$ C.await res `shouldBe` Just (sum [1..10]) + describe "mergeSource" $ do + it "works" $ do + let src :: C.Source IO String + src = CL.sourceList ["A", "B", "C"] + withIndex :: C.Conduit String IO (Integer, String) + withIndex = CI.mergeSource (CL.sourceList [1..]) + output <- src C.$= withIndex C.$$ CL.consume + output `shouldBe` [(1, "A"), (2, "B"), (3, "C")] + it "does stop processing when the source exhausted" $ do + let src :: C.Source IO Integer + src = CL.sourceList [1..] + withShortAlphaIndex :: C.Conduit Integer IO (String, Integer) + withShortAlphaIndex = CI.mergeSource (CL.sourceList ["A", "B", "C"]) + output <- src C.$= withShortAlphaIndex C.$$ CL.consume + output `shouldBe` [("A", 1), ("B", 2), ("C", 3)] + + let modFlag ref cur next = do + prev <- I.atomicModifyIORef ref $ (,) next + prev `shouldBe` cur + flagShouldBe ref expect = do + cur <- I.readIORef ref + cur `shouldBe` expect + it "properly run the finalizer - When the main Conduit is fully consumed" $ do + called <- I.newIORef ("RawC" :: String) + let src :: MonadIO m => C.Source m String + src = CL.sourceList ["A", "B", "C"] + withIndex :: MonadIO m => C.Conduit String m (Integer, String) + withIndex = C.addCleanup (\f -> liftIO $ modFlag called "AllocC-3" ("FinalC:" ++ show f)) . CI.mergeSource $ do + liftIO $ modFlag called "RawC" "AllocC-1" + C.yield 1 + liftIO $ modFlag called "AllocC-1" "AllocC-2" + C.yield 2 + liftIO $ modFlag called "AllocC-2" "AllocC-3" + C.yield 3 + liftIO $ modFlag called "AllocC-3" "AllocC-4" + C.yield 4 + output <- src C.$= withIndex C.$$ CL.consume + output `shouldBe` [(1, "A"), (2, "B"), (3, "C")] + called `flagShouldBe` "FinalC:True" + it "properly run the finalizer - When the branch Source is fully consumed" $ do + called <- I.newIORef ("RawS" :: String) + let src :: MonadIO m => C.Source m Integer + src = CL.sourceList [1..] + withIndex :: MonadIO m => C.Conduit Integer m (String, Integer) + withIndex = C.addCleanup (\f -> liftIO $ modFlag called "AllocS-C" ("FinalS:" ++ show f)) . CI.mergeSource $ do + liftIO $ modFlag called "RawS" "AllocS-A" + C.yield "A" + liftIO $ modFlag called "AllocS-A" "AllocS-B" + C.yield "B" + liftIO $ modFlag called "AllocS-B" "AllocS-C" + C.yield "C" + output <- src C.$= withIndex C.$$ CL.consume + output `shouldBe` [("A", 1), ("B", 2), ("C", 3)] + called `flagShouldBe` "FinalS:True" + it "properly DO NOT run the finalizer - When nothing consumed" $ do + called <- I.newIORef ("Raw0" :: String) + let src :: MonadIO m => C.Source m String + src = CL.sourceList ["A", "B", "C"] + withIndex :: MonadIO m => C.Conduit String m (Integer, String) + withIndex = C.addCleanup (\f -> liftIO $ modFlag called "WONT CALLED" ("Final0:" ++ show f)) . CI.mergeSource $ do + liftIO $ modFlag called "Raw0" "Alloc0-1" + C.yield 1 + output <- src C.$= withIndex C.$$ return () + output `shouldBe` () + called `flagShouldBe` "Raw0" + it "properly run the finalizer - When only one item consumed" $ do + called <- I.newIORef ("Raw1" :: String) + let src :: MonadIO m => C.Source m Integer + src = CL.sourceList [1..] + withIndex :: MonadIO m => C.Conduit Integer m (String, Integer) + withIndex = C.addCleanup (\f -> liftIO $ modFlag called "Alloc1-A" ("Final1:" ++ show f)) . CI.mergeSource $ do + liftIO $ modFlag called "Raw1" "Alloc1-A" + C.yield "A" + liftIO $ modFlag called "Alloc1-A" "Alloc1-B" + C.yield "B" + liftIO $ modFlag called "Alloc1-B" "Alloc1-C" + C.yield "C" + output <- src C.$= withIndex C.$= CL.isolate 1 C.$$ CL.consume + output `shouldBe` [("A", 1)] + called `flagShouldBe` "Final1:False" + + it "handles finalizers" $ do + ref <- I.newIORef (0 :: Int) + let src1 = C.addCleanup + (const $ I.modifyIORef ref (+1)) + (mapM_ C.yield [1 :: Int ..]) + src2 = mapM_ C.yield ("hi" :: String) + res1 <- src1 C.$$ C.mergeSource src2 C.=$ CL.consume + res1 `shouldBe` [('h', 1), ('i', 2)] + i1 <- I.readIORef ref + i1 `shouldBe` 1 + + res2 <- src2 C.$$ C.mergeSource src1 C.=$ CL.consume + res2 `shouldBe` [(1, 'h'), (2, 'i')] + i2 <- I.readIORef ref + i2 `shouldBe` 2 + describe "passthroughSink" $ do it "works" $ do ref <- I.newIORef (-1) @@ -966,6 +1064,15 @@ res <- src' C.$$ CL.consume res `shouldBe` [1, 3] + describe "sourceToList" $ do + it "works lazily in Identity" $ do + let src = C.yield 1 >> C.yield 2 >> throw DummyError + let res = runIdentity $ C.sourceToList src + take 2 res `shouldBe` [1, 2 :: Int] + it "is not lazy in IO" $ do + let src = C.yield 1 >> C.yield (2 :: Int) >> throw DummyError + C.sourceToList src `shouldThrow` (==DummyError) + ZipConduit.spec Stream.spec