polysemy-process 0.7.0.0 → 0.8.0.0
raw patch · 9 files changed
+141/−69 lines, 9 filesdep +tasty-expected-failuredep ~polysemy-timePVP ok
version bump matches the API change (PVP)
Dependencies added: tasty-expected-failure
Dependency ranges changed: polysemy-time
API changes (from Hackage documentation)
+ Polysemy.Process: KillAfter :: NanoSeconds -> ProcessKill
+ Polysemy.Process: KillImmediately :: ProcessKill
+ Polysemy.Process: KillNever :: ProcessKill
+ Polysemy.Process: ProcessOptions :: Bool -> Int -> ProcessKill -> ProcessOptions
+ Polysemy.Process: data ProcessKill
+ Polysemy.Process: data ProcessOptions
+ Polysemy.Process.Data.ProcessKill: KillAfter :: NanoSeconds -> ProcessKill
+ Polysemy.Process.Data.ProcessKill: KillImmediately :: ProcessKill
+ Polysemy.Process.Data.ProcessKill: KillNever :: ProcessKill
+ Polysemy.Process.Data.ProcessKill: data ProcessKill
+ Polysemy.Process.Data.ProcessKill: instance GHC.Classes.Eq Polysemy.Process.Data.ProcessKill.ProcessKill
+ Polysemy.Process.Data.ProcessKill: instance GHC.Show.Show Polysemy.Process.Data.ProcessKill.ProcessKill
+ Polysemy.Process.Data.ProcessOptions: ProcessOptions :: Bool -> Int -> ProcessKill -> ProcessOptions
+ Polysemy.Process.Data.ProcessOptions: [$sel:discard:ProcessOptions] :: ProcessOptions -> Bool
+ Polysemy.Process.Data.ProcessOptions: [$sel:kill:ProcessOptions] :: ProcessOptions -> ProcessKill
+ Polysemy.Process.Data.ProcessOptions: [$sel:qsize:ProcessOptions] :: ProcessOptions -> Int
+ Polysemy.Process.Data.ProcessOptions: data ProcessOptions
+ Polysemy.Process.Data.ProcessOptions: instance Data.Default.Class.Default Polysemy.Process.Data.ProcessOptions.ProcessOptions
+ Polysemy.Process.Data.ProcessOptions: instance GHC.Classes.Eq Polysemy.Process.Data.ProcessOptions.ProcessOptions
+ Polysemy.Process.Data.ProcessOptions: instance GHC.Show.Show Polysemy.Process.Data.ProcessOptions.ProcessOptions
- Polysemy.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
+ Polysemy.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
- Polysemy.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcess :: forall resource err o e r. Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessByteString :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessByteStringLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessText :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => Bool -> Int -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.Process: interpretProcessTextLines :: forall resource err r. Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r => ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
- Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => Bool -> Int -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
+ Polysemy.Process.Interpreter.ProcessStdio: interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r => ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r
Files
- changelog.md +4/−0
- lib/Polysemy/Process.hs +4/−0
- lib/Polysemy/Process/Data/ProcessKill.hs +16/−0
- lib/Polysemy/Process/Data/ProcessOptions.hs +21/−0
- lib/Polysemy/Process/Interpreter/Process.hs +47/−35
- lib/Polysemy/Process/Interpreter/ProcessStdio.hs +13/−24
- polysemy-process.cabal +5/−1
- test/Main.hs +2/−5
- test/Polysemy/Process/Test/ProcessTest.hs +29/−4
changelog.md view
@@ -1,3 +1,7 @@+# 0.8.0.0+* Add `ProcessOptions`, replacing the primitive parameters of `Process` interpreters.+* Add an option for `Process` that determines whether to kill the process after exiting the scope.+ # 0.6.0.0 * Allow `Process` to emit custom chunks constructed by an interpreter of `ProcessOutput` instead of `ByteString`s
lib/Polysemy/Process.hs view
@@ -10,6 +10,8 @@ recvError, send, withProcess,+ ProcessOptions (ProcessOptions),+ ProcessKill (..), -- ** ProcessOutput ProcessOutput,@@ -57,6 +59,8 @@ import Prelude hiding (send) +import Polysemy.Process.Data.ProcessKill (ProcessKill (..))+import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions)) import Polysemy.Process.Effect.Process (Process (..), recv, recvError, send, withProcess) import Polysemy.Process.Effect.ProcessOutput (ProcessOutput) import Polysemy.Process.Effect.Pty (Pty, withPty)
+ lib/Polysemy/Process/Data/ProcessKill.hs view
@@ -0,0 +1,16 @@+-- |Data type indicating whether to kill a process after exiting its scope.+module Polysemy.Process.Data.ProcessKill where++import Polysemy.Time (NanoSeconds)++-- |Indicate whether to kill a process after exiting the scope in which it was used, if it hasn't terminated.+data ProcessKill =+ -- |Wait for the specified interval, then kill.+ KillAfter NanoSeconds+ |+ -- |Kill immediately.+ KillImmediately+ |+ -- |Wait indefinitely for the process to terminate.+ KillNever+ deriving stock (Eq, Show)
+ lib/Polysemy/Process/Data/ProcessOptions.hs view
@@ -0,0 +1,21 @@+-- |Data type containing options for processes.+module Polysemy.Process.Data.ProcessOptions where++import qualified Polysemy.Process.Data.ProcessKill as ProcessKill+import Polysemy.Process.Data.ProcessKill (ProcessKill)++-- |Controls the behaviour of 'Polysemy.Process.Process' interpreters.+data ProcessOptions =+ ProcessOptions {+ -- |Whether to discard output chunks if the queue is full.+ discard :: Bool,+ -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.+ qsize :: Int,+ -- |What to do if the process hasn't terminated when exiting the scope.+ kill :: ProcessKill+ }+ deriving stock (Eq, Show)++instance Default ProcessOptions where+ def =+ ProcessOptions True 1024 ProcessKill.KillImmediately
lib/Polysemy/Process/Interpreter/Process.hs view
@@ -4,6 +4,7 @@ module Polysemy.Process.Interpreter.Process where import Control.Concurrent.STM.TBMQueue (TBMQueue)+import qualified Polysemy.Conc as Conc import Polysemy.Conc.Async (withAsync_) import qualified Polysemy.Conc.Data.QueueResult as QueueResult import qualified Polysemy.Conc.Effect.Queue as Queue@@ -12,10 +13,12 @@ import Polysemy.Conc.Effect.Scoped (Scoped) import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBMWith, withTBMQueue) import Polysemy.Conc.Interpreter.Scoped (interpretScopedResumableWith_)-import Polysemy.Resume (Stop, resumeOr, stop, type (!!))+import Polysemy.Resume (Stop, resumeOr, stop, type (!!), resuming) import Prelude hiding (fromException) import Polysemy.Process.Data.ProcessError (ProcessError (Terminated))+import Polysemy.Process.Data.ProcessKill (ProcessKill (KillAfter, KillImmediately, KillNever))+import Polysemy.Process.Data.ProcessOptions (ProcessOptions (ProcessOptions)) import qualified Polysemy.Process.Effect.Process as Process import Polysemy.Process.Effect.Process (Process) import qualified Polysemy.Process.Effect.ProcessOutput as ProcessOutput@@ -135,6 +138,30 @@ _ -> unit +handleKill ::+ Members [SystemProcess, Race] r =>+ ProcessKill ->+ Sem r ()+handleKill = \case+ KillAfter interval ->+ Conc.timeout_ SystemProcess.term interval (void SystemProcess.wait)+ KillImmediately ->+ SystemProcess.term+ KillNever ->+ void (dbgs =<< SystemProcess.wait)++withKill ::+ ∀ err r a .+ Members [SystemProcess !! err, Resource, Race] r =>+ ProcessKill ->+ Sem r a ->+ Sem r a+withKill kill ma =+ ma <* resuming @err @SystemProcess (\ _ -> dbg "resume") do+ void SystemProcess.pid+ dbg "killing"+ handleKill kill+ type ScopeEffects o e err = [Queue (In ByteString), Queue (Out o), Queue (Err e), SystemProcess !! err] @@ -142,15 +169,15 @@ ∀ o e resource err r . Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput e, ProcessOutput o, Resource, Race, Async, Embed IO] r =>- Bool ->- Int ->+ ProcessOptions -> InterpretersFor (ScopeEffects o e err) r-scope discard qSize =+scope (ProcessOptions discard qSize kill) = withSystemProcess @resource . withQueues qSize . withAsync_ (outputQueue @Err @e @err discard SystemProcess.readStderr) . withAsync_ (outputQueue @Out @o @err discard SystemProcess.readStdout) .- withAsync_ (inputQueue @err SystemProcess.writeStdin)+ withAsync_ (inputQueue @err SystemProcess.writeStdin) .+ withKill @err kill -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's, -- deferring decoding of stdout and stderr to the interpreters of two 'ProcessOutput' effects.@@ -158,27 +185,21 @@ ∀ resource err o e r . Member (Scoped resource (SystemProcess !! err)) r => Members [ProcessOutput o, ProcessOutput e, Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full or block.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> InterpreterFor (Scoped () (Process ByteString o e) !! ProcessError) r-interpretProcess discard qSize =- interpretScopedResumableWith_ @(ScopeEffects o e err) (scope @o @e @resource discard qSize) handleProcessWithQueues+interpretProcess options =+ interpretScopedResumableWith_ @(ScopeEffects o e err) (scope @o @e @resource options) handleProcessWithQueues -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's, -- producing 'ByteString's. interpretProcessByteString :: ∀ resource err r . Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r-interpretProcessByteString discard qSize =+interpretProcessByteString options = interpretProcessOutputId .- interpretProcess @resource @err discard qSize .+ interpretProcess @resource @err options . raiseUnder -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,@@ -186,14 +207,11 @@ interpretProcessByteStringLines :: ∀ resource err r . Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r-interpretProcessByteStringLines discard qSize =+interpretProcessByteStringLines options = interpretProcessOutputLines .- interpretProcess @resource @err discard qSize .+ interpretProcess @resource @err options . raiseUnder -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,@@ -201,14 +219,11 @@ interpretProcessText :: ∀ resource err r . Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r-interpretProcessText discard qSize =+interpretProcessText options = interpretProcessOutputText .- interpretProcess @resource @err discard qSize .+ interpretProcess @resource @err options . raiseUnder -- |Interpret 'Process' with a system process resource whose file descriptors are connected to three 'TBMQueue's,@@ -216,12 +231,9 @@ interpretProcessTextLines :: ∀ resource err r . Members [Scoped resource (SystemProcess !! err), Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r-interpretProcessTextLines discard qSize =+interpretProcessTextLines options = interpretProcessOutputTextLines .- interpretProcess @resource @err discard qSize .+ interpretProcess @resource @err options . raiseUnder
lib/Polysemy/Process/Interpreter/ProcessStdio.hs view
@@ -9,6 +9,7 @@ import System.Process.Typed (ProcessConfig) import Polysemy.Process.Data.ProcessError (ProcessError)+import Polysemy.Process.Data.ProcessOptions (ProcessOptions) import Polysemy.Process.Data.SystemProcessError (SystemProcessError) import Polysemy.Process.Effect.Process (Process) import Polysemy.Process.Interpreter.Process (@@ -23,58 +24,46 @@ interpretProcessByteStringNative :: Members [Resource, Race, Async, Embed IO] r => -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->- -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter.+ ProcessOptions -> ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r-interpretProcessByteStringNative discard qSize conf =+interpretProcessByteStringNative options conf = interpretSystemProcessNative conf .- interpretProcessByteString @PipesProcess @SystemProcessError discard qSize .+ interpretProcessByteString @PipesProcess @SystemProcessError options . raiseUnder -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing lines of 'ByteString'. interpretProcessByteStringLinesNative :: Members [Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter. ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString ByteString ByteString) !! ProcessError) r-interpretProcessByteStringLinesNative discard qSize conf =+interpretProcessByteStringLinesNative options conf = interpretSystemProcessNative conf .- interpretProcessByteStringLines @PipesProcess @SystemProcessError discard qSize .+ interpretProcessByteStringLines @PipesProcess @SystemProcessError options . raiseUnder -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing unaccumulated chunks of 'Text'. interpretProcessTextNative :: Members [Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter. ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r-interpretProcessTextNative discard qSize conf =+interpretProcessTextNative options conf = interpretSystemProcessNative conf .- interpretProcessText @PipesProcess @SystemProcessError discard qSize .+ interpretProcessText @PipesProcess @SystemProcessError options . raiseUnder -- |Interpret 'Process' as a native 'Polysemy.Process.SystemProcess', producing lines of 'Text'. interpretProcessTextLinesNative :: Members [Resource, Race, Async, Embed IO] r =>- -- |Whether to discard output chunks if the queue is full.- Bool ->- -- |Maximum number of chunks allowed to be queued for each of the three standard pipes.- Int ->+ ProcessOptions -> -- |Basic config. The pipes will be changed to 'System.IO.Handle' by the interpreter. ProcessConfig () () () -> InterpreterFor (Scoped () (Process ByteString Text Text) !! ProcessError) r-interpretProcessTextLinesNative discard qSize conf =+interpretProcessTextLinesNative options conf = interpretSystemProcessNative conf .- interpretProcessTextLines @PipesProcess @SystemProcessError discard qSize .+ interpretProcessTextLines @PipesProcess @SystemProcessError options . raiseUnder
polysemy-process.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: polysemy-process-version: 0.7.0.0+version: 0.8.0.0 synopsis: Polysemy Effects for System Processes description: See <https://hackage.haskell.org/package/polysemy-process/docs/Polysemy-Process.html> category: Concurrency@@ -29,6 +29,8 @@ exposed-modules: Polysemy.Process Polysemy.Process.Data.ProcessError+ Polysemy.Process.Data.ProcessKill+ Polysemy.Process.Data.ProcessOptions Polysemy.Process.Data.PtyError Polysemy.Process.Data.PtyResources Polysemy.Process.Data.SystemProcessError@@ -114,6 +116,7 @@ , polysemy >=1.6 , polysemy-conc , polysemy-resume >=0.3+ , polysemy-time >=0.4 , posix-pty >=0.2 , process , stm-chans >=2@@ -202,6 +205,7 @@ , polysemy-test , polysemy-time , tasty+ , tasty-expected-failure , typed-process mixins: base hiding (Prelude)
test/Main.hs view
@@ -1,15 +1,12 @@ module Main where -import Polysemy.Process.Test.ProcessTest (test_process)-import Polysemy.Test (unitTest)+import Polysemy.Process.Test.ProcessTest (test_processAll) import Test.Tasty (TestTree, defaultMain, testGroup) tests :: TestTree tests = testGroup "main" [- testGroup "process" [- unitTest "process" test_process- ]+ test_processAll ] main :: IO ()
test/Polysemy/Process/Test/ProcessTest.hs view
@@ -2,16 +2,21 @@ module Polysemy.Process.Test.ProcessTest where +import qualified Polysemy.Conc as Conc import Polysemy.Conc.Effect.Scoped (Scoped) import Polysemy.Conc.Interpreter.Race (interpretRace) import qualified Polysemy.Conc.Race as Race import Polysemy.Resume (resumeHoistError)-import Polysemy.Test (UnitTest, runTestAuto, (===))-import Polysemy.Time (Seconds (Seconds))+import Polysemy.Test (UnitTest, assertLeft, runTestAuto, unitTest, (===))+import Polysemy.Time (MilliSeconds (MilliSeconds), Seconds (Seconds)) import qualified System.Process.Typed as Process import System.Process.Typed (ProcessConfig)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.ExpectedFailure (ignoreTest) import Polysemy.Process.Data.ProcessError (ProcessError)+import Polysemy.Process.Data.ProcessKill (ProcessKill (KillNever))+import Polysemy.Process.Data.ProcessOptions (ProcessOptions (kill)) import qualified Polysemy.Process.Effect.Process as Process import Polysemy.Process.Effect.Process (withProcess) import Polysemy.Process.Interpreter.ProcessStdio (interpretProcessByteStringNative, interpretProcessTextLinesNative)@@ -30,7 +35,7 @@ test_process :: UnitTest test_process =- runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessByteStringNative True 10 config do+ runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessByteStringNative def config do response <- resumeHoistError @ProcessError @(Scoped _ _) show do withProcess do Process.send message@@ -39,9 +44,29 @@ test_processLines :: UnitTest test_processLines =- runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessTextLinesNative True 10 config do+ runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessTextLinesNative def config do response <- resumeHoistError @ProcessError @(Scoped _ _) show do withProcess do Process.send message Race.timeout_ (throw "timed out") (Seconds 5) (replicateM 4 Process.recv) messageLines === response++test_processKill :: UnitTest+test_processKill =+ runTestAuto $ interpretRace $ asyncToIOFinal $ interpretProcessTextLinesNative def { kill = KillNever } config do+ result <- resumeHoistError @ProcessError @(Scoped _ _) show do+ Conc.timeout unit (MilliSeconds 100) do+ withProcess do+ Process.send message+ Process.recv+ -- This does not succeed. It should be 'Left', but apparently the `timeout` causes the `SystemProcess` scope to stop+ -- the process and makes the right side terminate regularly.+ assertLeft () result++test_processAll :: TestTree+test_processAll =+ testGroup "process" [+ unitTest "process" test_process,+ unitTest "process lines" test_processLines,+ ignoreTest (unitTest "process kill" test_processKill)+ ]