Skip to content

Commit

Permalink
Add pretty option to dump operator [ci fast]
Browse files Browse the repository at this point in the history
Signed-off-by: Paolo Di Tommaso <[email protected]>
  • Loading branch information
pditommaso committed Oct 2, 2022
1 parent 02afa33 commit 4218b29
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 15 deletions.
5 changes: 5 additions & 0 deletions docs/operator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ Then you will be able to specify the tag ``foo`` or ``bar`` as an argument of th
either the content of the first or the second channel. Multiple tag names can be specified separating them with a ``,``
character.

The output can be formatted using the optional ``pretty`` boolean option. For example::

Channel
.fromSRA('SRP043510')
.dump(tag:'foo', pretty: true)

filter
------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2020-2022, Seqera Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package nextflow.extension

import java.nio.file.Path

import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.transform.CompileStatic
import nextflow.extension.FilesEx
import org.codehaus.groovy.runtime.InvokerHelper
/**
* Helper converters for {@link DumpOp} operator
*
* @author : jorge <[email protected]>
*/
@CompileStatic
class DumpHelper {

static def deepReplaceToString(root, replaceNullWith = "") {
if (root instanceof List) {
root.collect {
if (it instanceof Map) {
deepReplaceToString(it, replaceNullWith)
} else if (it instanceof List) {
deepReplaceToString(it, replaceNullWith)
} else if (it == null) {
replaceNullWith
} else if (it instanceof Path) {
FilesEx.toUriString(it)
} else {
it.toString()
}
}
}
else if (root instanceof Map) {
root.each {
if (it.value instanceof Map) {
deepReplaceToString(it.value, replaceNullWith)
} else if (it.value instanceof List) {
it.value = deepReplaceToString(it.value, replaceNullWith)
} else if (it.value == null) {
it.value = replaceNullWith
} else if (it.value instanceof Path) {
return FilesEx.toUriString((Path)it.value)
} else {
it.value = it.value.toString()
}
}
}
}

static String prettyPrint(input){
if (input instanceof Map) {
def converted = deepReplaceToString(input)
return JsonOutput.prettyPrint(JsonOutput.toJson(converted))
} else if (input instanceof List) {
def converted = deepReplaceToString(input)
return new JsonBuilder(converted).toPrettyString()
} else if (input instanceof Path) {
return FilesEx.toUriString(input)
} else {
return InvokerHelper.inspect(input)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import static nextflow.util.CheckHelper.checkParams
@CompileStatic
class DumpOp {

static final private Map PARAMS_DUMP = [tag: String]
static final private Map PARAMS_DUMP = [tag: String, pretty: Boolean ]

private Session session = (Global.session as Session)

Expand All @@ -48,10 +48,13 @@ class DumpOp {

protected String tag

protected boolean pretty

DumpOp(Map opts, Closure<String> renderer) {
checkParams('dump', opts, PARAMS_DUMP)
this.source = source
this.tag = opts.tag
this.pretty = opts.pretty ?: false
this.renderer = renderer
this.dumpNames = session.getDumpChannels()
}
Expand Down Expand Up @@ -88,7 +91,7 @@ class DumpOp {
events.onNext = {
def marker = 'DUMP'
if( tag ) marker += ": $tag"
log.info "[$marker] " + ( renderer ? renderer.call(it) : InvokerHelper.inspect(it) )
log.info "[$marker] " + ( renderer ? renderer.call(it) : pretty ? DumpHelper.prettyPrint(it) : InvokerHelper.inspect(it) )
target.bind(it)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import nextflow.Session
import spock.lang.Specification
import spock.lang.Unroll
import test.OutputCapture

import java.nio.file.Path

/**
*
* @author Paolo Di Tommaso <[email protected]>
Expand All @@ -40,7 +43,7 @@ class DumpOpTest extends Specification {
new Session(dumpChannels: ['*'])

when:
def result = Channel.from(1,2,3).dump()
def result = Channel.from(1, 2, 3).dump()
then:
result.val == 1
result.val == 2
Expand All @@ -58,7 +61,7 @@ class DumpOpTest extends Specification {
new Session(dumpChannels: ['*'])

when:
def result = Channel.from(1,2,3).dump { it * it }
def result = Channel.from(1, 2, 3).dump { it * it }
then:
result.val == 1
result.val == 2
Expand All @@ -76,7 +79,7 @@ class DumpOpTest extends Specification {
new Session(dumpChannels: ['*'])

when:
def result = Channel.from(1,2,3).dump(tag:'foo')
def result = Channel.from(1, 2, 3).dump(tag: 'foo')
then:
result.val == 1
result.val == 2
Expand All @@ -89,7 +92,7 @@ class DumpOpTest extends Specification {
}

@Unroll
def 'should validate isEnabled when tag=#tag and names=#names' () {
def 'should validate isEnabled when tag=#tag and names=#names'() {

given:
def op = new DumpOp(tag: tag, dumpNames: names.tokenize(','))
Expand All @@ -98,16 +101,61 @@ class DumpOpTest extends Specification {
op.isEnabled() == expected

where:
tag | names | expected
'foo' | 'foo' | true
'foo' | '*' | true
'foo' | 'bar' | false
'foo' | 'f' | false
'foo' | 'f*' | true
'bar' | 'f*' | false
'bar' | 'f*,b*' | true
null | '*' | true
tag | names | expected
'foo' | 'foo' | true
'foo' | '*' | true
'foo' | 'bar' | false
'foo' | 'f' | false
'foo' | 'f*' | true
'bar' | 'f*' | false
'bar' | 'f*,b*' | true
null | '*' | true

}

@Unroll
def 'should pretty print channel with items #items'() {

given:
new Session(dumpChannels: ['*'])

when:
def result = Channel.of(items).dump(tag: 'foo', pretty: true)

then:
result.val
result.val == Channel.STOP
capture.toString().contains(expected)

where:
items | expected
'a string' | "[DUMP: foo] 'a string'"
123123 | '[DUMP: foo] 123123'
['a', 'b'] | '"a",'
['a': 'b'] | '"a": "b"'
['a': Path.of('b')] | '"a": "b"'
['a': [b: Path.of('c')]] | '"b": "c"'
}

def 'should pretty print a complex channel'() {

given:
new Session(dumpChannels: ['*'])

when:
def result = Channel.of([
id : 'test',
samples: [
[id: 'S1', path: '/path/to/s1'],
[id: 'S2', path: '/path/to/s2'],
[id: 'S3', path: '/path/to/s3']
]
]).dump(tag: 'foo', pretty: true)

then:
result.val
result.val == Channel.STOP
capture.toString().contains('"path": "/path/to/s1"')
}

}

0 comments on commit 4218b29

Please sign in to comment.