From cb66af826596b7bfba0fa45f8eb25fcf1613bc13 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Sun, 15 Oct 2023 12:13:58 +0100 Subject: ccwl: Make #:stderr and #:stdout first class parameters. #:stderr and #:stdout, especially #:stdout, are commonly required. They ought to be first class parameters and not tucked away into #:other. * ccwl/ccwl.scm ()[stderr, stdout]: New fields. * ccwl/ccwl.scm (command): Accept #:stderr and #:stdout as first class parameters. * ccwl/cwl.scm (command->cwl-scm): Serialize stderr and stdout fields. * doc/capture-stdout.scm (print), doc/decompress-compile-run.scm (run), doc/checksum.scm (md5sum, sha1sum, sha256sum), doc/spell-check.scm (find-misspellings): Capture stdout in file. * doc/checksum.scm, doc/decompress-compile-run.scm: * doc/ccwl.skb (Tutorial)[Capturing the standard output stream of a command]: Document #:stdout first class parameter. * doc/ccwl.skb (Tutorial)[Workflow with multiple steps]: Capture stdout in explicitly named files. * tests/ccwl.scm ("commands with non-string #:stderr parameters must raise a &ccwl-violation condition", "commands with non-string #:stdout parameters must raise a &ccwl-violation condition"): New tests. --- ccwl/ccwl.scm | 20 ++++++++++++++++++-- ccwl/cwl.scm | 6 ++++++ doc/capture-stdout.scm | 3 ++- doc/ccwl.skb | 18 ++++++++---------- doc/checksum.scm | 9 ++++++--- doc/decompress-compile-run.scm | 3 ++- doc/spell-check.scm | 3 ++- tests/ccwl.scm | 24 ++++++++++++++++++++++++ 8 files changed, 68 insertions(+), 18 deletions(-) diff --git a/ccwl/ccwl.scm b/ccwl/ccwl.scm index f64830c..05cb6e6 100644 --- a/ccwl/ccwl.scm +++ b/ccwl/ccwl.scm @@ -42,6 +42,8 @@ command-outputs command-args command-stdin + command-stderr + command-stdout command-other cwl-workflow? cwl-workflow @@ -186,12 +188,14 @@ (_ (error "Invalid output:" (syntax->datum output-spec))))) (define-immutable-record-type - (make-command inputs outputs args stdin other) + (make-command inputs outputs args stdin stderr stdout other) command? (inputs command-inputs set-command-inputs) (outputs command-outputs) (args command-args) (stdin command-stdin) + (stderr command-stderr) + (stdout command-stdout) (other command-other)) (define-immutable-record-type @@ -300,7 +304,7 @@ RUN-ARGS. If such an input is not present in RUN-ARGS, return #f." (condition (ccwl-violation extra) (formatted-message "Unexpected extra positional argument ~a in command definition" (syntax->datum extra)))))))) - (apply (syntax-lambda** (#:key stdin #:key* inputs outputs run other) + (apply (syntax-lambda** (#:key stdin stderr stdout #:key* inputs outputs run other) (when (null? run) (raise-exception (condition (ccwl-violation x) @@ -332,6 +336,18 @@ RUN-ARGS. If such an input is not present in RUN-ARGS, return #f." (syntax->datum x))))) run)) #,(and stdin #`'#,stdin) + #,(if (and stderr + (not (string? (syntax->datum stderr)))) + (raise-exception + (condition (ccwl-violation stderr) + (formatted-message "#:stderr parameter must be a string"))) + stderr) + #,(if (and stdout + (not (string? (syntax->datum stdout)))) + (raise-exception + (condition (ccwl-violation stdout) + (formatted-message "#:stdout parameter must be a string"))) + stdout) (list #,@other))) #'(args ...))))))) diff --git a/ccwl/cwl.scm b/ccwl/cwl.scm index 4c4fef0..30a6cb9 100644 --- a/ccwl/cwl.scm +++ b/ccwl/cwl.scm @@ -146,4 +146,10 @@ CWL YAML specification." (symbol->string (command-stdin command)) ".path)"))) + '()) + ,@(if (command-stderr command) + `((stderr . ,(command-stderr command))) + '()) + ,@(if (command-stdout command) + `((stdout . ,(command-stdout command))) '()))) diff --git a/doc/capture-stdout.scm b/doc/capture-stdout.scm index b9b6774..9eb19ca 100644 --- a/doc/capture-stdout.scm +++ b/doc/capture-stdout.scm @@ -1,7 +1,8 @@ (define print (command #:inputs (message #:type string) #:run "echo" message - #:outputs (printed-message #:type stdout))) + #:outputs (printed-message #:type stdout) + #:stdout "printed-message-output.txt")) (workflow ((message #:type string)) (print #:message message)) diff --git a/doc/ccwl.skb b/doc/ccwl.skb index e910452..39116ee 100644 --- a/doc/ccwl.skb +++ b/doc/ccwl.skb @@ -1,5 +1,5 @@ ;;; ccwl --- Concise Common Workflow Language -;;; Copyright © 2021 Arun Isaac +;;; Copyright © 2021, 2023 Arun Isaac ;;; ;;; This file is part of ccwl. ;;; @@ -116,8 +116,9 @@ as follows. The expected output is also shown.]) (p [Let us return to the ,(emph "Hello World") example in the previous section. But now, let us capture the standard output of the ,(code "print") command in an output object. The ccwl code is the same -as earlier with only the addition of an ,(code "stdout") type output -object to the command definition.]) +as earlier with the addition of an ,(code "stdout") type output object +and an ,(code "#:stdout") parameter specifying the name of the file to +capture standard output in.]) (scheme-source "doc/capture-stdout.scm") @@ -126,7 +127,7 @@ object to the command definition.]) ,(file "capture-stdout.cwl"), and run it using ,(code "cwltool"). We might expect something like the output below. Notice how the standard output of the ,(code "print") command has been captured in the file -,(file "51fe79d15e7790a9ded795304220d7a44aa84b48").]) +,(file "printed-message-output.txt").]) (prog :line #f (source :file "doc/capture-stdout.out"))) @@ -220,8 +221,7 @@ following output.]) (prog :line #f (source :file "doc/decompress-compile-run.out")) (p [The steps run in succession, and the stdout of the -compiled executable is in -,(file "c32c587f7afbdf87cf991c14a43edecf09cd93bf"). Success!])) +compiled executable is in ,(file "run-output.txt"). Success!])) (subsection :title [tee] (p [Next, the tee topology. The following workflow computes @@ -245,10 +245,8 @@ following output.]) (prog :line #f (source :file "doc/checksum.out")) - (p [The MD5, SHA1 and SHA256 checksums are in the files -,(file "112be1054505027982e64d56b0879049c12737c6"), -,(file "d2f19c786fcd3feb329004c8747803fba581a02d") and -,(file "0d2eaa5619c14b43326101200d0f27b0d8a1a4b1") respectively.]))) + (p [The MD5, SHA1 and SHA256 checksums are in the files ,(file +"md5"), ,(file "sha1") and ,(file "sha256") respectively.]))) (section :title [Let's write a spell check workflow] (p [Finally, let's put together a complex workflow to understand diff --git a/doc/checksum.scm b/doc/checksum.scm index 297ac14..9474964 100644 --- a/doc/checksum.scm +++ b/doc/checksum.scm @@ -1,17 +1,20 @@ (define md5sum (command #:inputs (file #:type File) #:run "md5sum" file - #:outputs (md5 #:type stdout))) + #:outputs (md5 #:type stdout) + #:stdout "md5")) (define sha1sum (command #:inputs (file #:type File) #:run "sha1sum" file - #:outputs (sha1 #:type stdout))) + #:outputs (sha1 #:type stdout) + #:stdout "sha1")) (define sha256sum (command #:inputs (file #:type File) #:run "sha256sum" file - #:outputs (sha256 #:type stdout))) + #:outputs (sha256 #:type stdout) + #:stdout "sha256")) (workflow ((file #:type File)) (tee (md5sum #:file file) diff --git a/doc/decompress-compile-run.scm b/doc/decompress-compile-run.scm index 00ad392..3513fd6 100644 --- a/doc/decompress-compile-run.scm +++ b/doc/decompress-compile-run.scm @@ -13,7 +13,8 @@ (define run (command #:inputs executable #:run executable - #:outputs (stdout #:type stdout))) + #:outputs (stdout #:type stdout) + #:stdout "run-output.txt")) (workflow ((compressed-source #:type File)) (pipe (decompress #:compressed compressed-source) diff --git a/doc/spell-check.scm b/doc/spell-check.scm index 1f05154..d5ccebb 100644 --- a/doc/spell-check.scm +++ b/doc/spell-check.scm @@ -19,7 +19,8 @@ (define find-misspellings (command #:inputs words dictionary #:run "comm" "-23" words dictionary - #:outputs (misspellings #:type stdout))) + #:outputs (misspellings #:type stdout) + #:stdout "misspelt-words")) (workflow (text-file dictionary) (pipe (tee (pipe (split-words #:text text-file) diff --git a/tests/ccwl.scm b/tests/ccwl.scm index 76bcecd..e7a0cb7 100644 --- a/tests/ccwl.scm +++ b/tests/ccwl.scm @@ -197,4 +197,28 @@ (print (print2) #:message message2))) #f))) +(test-assert "commands with non-string #:stderr parameters must raise a &ccwl-violation condition" + (guard (exception + (else (and (ccwl-violation? exception) + (string=? (formatted-message-format exception) + "#:stderr parameter must be a string")))) + (begin (macroexpand + '(command #:inputs (message #:type string) + #:run "echo" message + #:outputs (printed #:type stderr) + #:stderr captured-stderr)) + #f))) + +(test-assert "commands with non-string #:stdout parameters must raise a &ccwl-violation condition" + (guard (exception + (else (and (ccwl-violation? exception) + (string=? (formatted-message-format exception) + "#:stdout parameter must be a string")))) + (begin (macroexpand + '(command #:inputs (message #:type string) + #:run "echo" message + #:outputs (printed #:type stdout) + #:stdout captured-stdout)) + #f))) + (test-end "ccwl") -- cgit v1.2.3