0

When using the invoke library from Windows, it seems like no output is printed to the terminal if the command spans multiple lines. Here's an example to reproduce; put this in tasks.py.

import invoke

@invoke.task
def test_oneline(ctx):
    ctx.run("pip install nonexistant-package1234")

@invoke.task
def test_multiline(ctx):
    ctx.run(
    """
    pip install nonexistant-package1234
    """
    )

Then, from the command prompt in the same directory as tasks.py, I get the following:

>invoke test-oneline
Collecting nonexistant-package1234
  Could not find a version that satisfies the requirement nonexistant-package1234 (from versions: )
No matching distribution found for nonexistant-package1234
>
>invoke test-multiline

>

Doing the same thing on Linux (well, at least Windows Subsystem for Linux) works as expected:

$ invoke test-multiline
Collecting nonexistant-package1234
  Could not find a version that satisfies the requirement nonexistant-package1234 (from versions: )
No matching distribution found for nonexistant-package1234
$

Is there a way to get the output printed in Windows for multi-line commands?

Nathan
  • 9,651
  • 4
  • 45
  • 65

1 Answers1

0

Here's the hack that I'm using for now in case others need to circumvent this in the short run. I'll post back if I encounter issues with it; it's only minimally tested so far. Basically, if you're on Windows, I just write the command into a .bat file, then I run the .bat file (as a single-line command).

import invoke
import platform
from pathlib import Path
from tempfile import TemporaryDirectory


def _fixed_run(ctx, cmd: str, *args, **kwargs):
    if platform.system() != "Windows":
        return ctx._old_run(cmd, *args, **kwargs)

    with TemporaryDirectory() as tmp_dir:
        tmp_file = Path(tmp_dir) / "tmp.bat"
        tmp_file.write_text("@echo off\r\n" + cmd)
        return ctx._old_run(str(tmp_file), *args, **kwargs)

invoke.Context._old_run = invoke.Context.run
invoke.Context.run = _fixed_run

To use this easily, save it into a file (e.g. fix_invoke.py and then just do import fix_invoke whenever you need this fix).

I'd be glad to hear of a real solution, though, if anybody has one!

Nathan
  • 9,651
  • 4
  • 45
  • 65