con / duct

A helper to run a command, capture stdout/stderr and details about running
MIT License
1 stars 1 forks source link

add [--] into --help output #51

Closed yarikoptic closed 3 weeks ago

yarikoptic commented 3 weeks ago

so instead of

usage: duct [-h] [-p OUTPUT_PREFIX] [--sample-interval SAMPLE_INTERVAL] [--report-interval REPORT_INTERVAL] [-c {all,none,stdout,stderr}] [-o {all,none,stdout,stderr}]
            [-t {all,system-summary,processes-samples}]
            command [arguments ...]

looks like

usage: duct [-h] [-p OUTPUT_PREFIX] [--sample-interval SAMPLE_INTERVAL] [--report-interval REPORT_INTERVAL] [-c {all,none,stdout,stderr}] [-o {all,none,stdout,stderr}]
            [-t {all,system-summary,processes-samples}]
            [--] command [arguments ...]

and add description on -- as to be recommended to ensure that arguments are not treated as arguments to duct.

On the other hand, I think we might need to look into how to tune argparser here: ideally we should automagically stop parsing when reaching command. @jwodder , you did some heavy CLI parsing tune up in datalad-installer, may be you know what would be the best way here to ensure that parsing stops and [arguments] for the command do not interfer with our duct arguments?

jwodder commented 3 weeks ago

@yarikoptic Unless duct is calling parser.parse_intermixed_args(), I think it should stop at the first non-option argument by default.

asmacdo commented 3 weeks ago

duct is using parser.parse_args()

https://github.com/con/duct/blob/0eec46d9c7527a7f17d3205447223f27b622aa87/src/duct.py#L271

yarikoptic commented 3 weeks ago

not quite -- it does consume [arguments] and spits out error, e.g. we get

image

for

yoh@typhon:/tmp/repro-TccSlQF/ds000003-qc$ cat .datalad/config 
[datalad "dataset"]
        id = 621f77c3-4a35-4147-8146-67fa49b66369
[datalad "containers.bids-mriqc"]
        image = containers/images/bids/bids-mriqc--0.16.0.sing
        cmdexec = duct {img_dspath}/containers/scripts/singularity_cmd run {img} {cmd}

in repronim/containers - I had to add -- after duct there

jwodder commented 3 weeks ago

Then try parse_known_args() instead.

asmacdo commented 3 weeks ago

parese_known_args does work but at first glance (not thorough) it seems like there wouldn't be any way to pass args to the inner command that happen to have the same name as a duct arg.

jwodder commented 3 weeks ago

Is there a reason you need to use argparse in the first place? Click is really the better option for both this sort of thing and in general.

asmacdo commented 3 weeks ago

We wanted duct to be "pure" to be as portable as possible.

jwodder commented 3 weeks ago

The undocumented nargs value argparse.REMAINDER should do what you want:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-f", "--foo")
parser.add_argument("rest", nargs=argparse.REMAINDER)

print(parser.parse_args(["bar", "--foo", "quux"]))
# Prints: Namespace(foo=None, rest=['bar', '--foo', 'quux'])