argcomplete icon indicating copy to clipboard operation
argcomplete copied to clipboard

Interaction between scripts that both use argcomplete

Open benmaddison opened this issue 4 years ago • 0 comments

I'm leaving this here mostly for posterity, as this issue don't seem to have been encountered (or at least written down) before, and hopefully it will save someone the hours of debugging that I've just been through!

I am writing a CLI tool that spawns a subprocess (via subprocess.run) early on in its init phase, before the parser construction is finished.

The subprocess is a call to ansible-inventory, which itself happens to use argcomplete.

As a result argcomplete.autocomplete is called in the child process before it is called in the parent. By default, all the subprocess.Popen wrappers copy os.environ verbatim to the child process, including _ARGCOMPLETE=1 if present. Of course the child doesn't have an fd8, so the child exits with return code 1.

The parent (in our case) raises an exception on the non-zero return from the child, and bang everything breaks.

The debug output contains no indication that the Unable to open fd 8 for writing, quitting message is actually being emitted by a different process, so piecing this together is not trivial!

The workaround, if you encounter this, is to strip all the completion-specific environment vars before the subprocess call:

def foo():
    ...
    env = {k: v for k, v in os.environ.items()
           if not (k.startswith("COMP_") or
                   k.startswith("_ARGCOMPLETE") or
                   k == "IFS")}
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env)
    ...

I'm not sure that there is an easy fix for this within argcomplete. Perhaps another environment variable that indicates the executable being completed? The above fix is easy enough now that I understand what's going on ;-)

benmaddison avatar Oct 27 '20 15:10 benmaddison