isort doesn't wait for EOF when reading from stdin

Created on 13 Nov 2020  路  10Comments  路  Source: PyCQA/isort

When reading from stdin, isort starts outputting without waiting for EOF. This is fine when one wants to pipe cat file.py output, but it makes it impossible to just copy-paste some python code and get it with imports sorted.

integration invalid question

All 10 comments

Hi @utkarshgupta137,

I can understand the desire to be able to copy and past code and have it quickly sorted, but might I suggest using https://pycqa.github.io/isort/docs/quick_start/0.-try/ or vs code or QuickPython to do it?

It is by design that isort doesn't wait for EOF. Doing so would make the designed for case that you described (piping files as used by certain integration such as VS Code) perform worse and increase the memory requirement of isort. isort uses a streaming architecture and sorts as it sees contiguous areas of imports.

Thanks!

~Timothy

I'm writing an isort (+ black) plugin for atom. I wish to isort the contents in buffer, without having to save the file.

Can you suggest a way to do it (using js) other than spawning a python process or writing to a temp file & copying it over?

If you're interested in adding this feature, I'm willing to work on it if you can point me in the right direction.

@utkarshgupta137 an atom plugin for isort + black sounds great!

If I understand correctly, your goal then is to essentially keep the pipe open and keep sending content to it?
I'm not really familiar enough with non web JS to know off-hand how to accomplish this in that scenario, but I think it is separate from the the tickets implied description asking for isort to buffer until EOF, and should already be possible. Here's a Python example that shows a pipe to isort that is kept open over multiple runs:

from subprocess import PIPE, Popen

proc = Popen(("isort", "-"), stdin=PIPE, stdout=PIPE)
proc.stdin.write(
    """
import b
import a
EOF
""".encode()
)
proc.stdin.flush()


def text_until_end():
    text = ""
    while True:
        line = proc.stdout.readline().decode()
        if line.strip() == "EOF":
            break
        text += line
    return text


sorted1 = text_until_end()


proc.stdin.write(
    """
import c
import b
EOF
""".encode()
)
proc.stdin.flush()
sorted2 = text_until_end()

print(
    f"""
sorted1:
{sorted1}

sorted2:
{sorted2}
"""
)

No, I don't intend to keep the buffer open. I'm using node.js's child_process.spawn (Actually a wrapper provider by atom). I'm doing:

      process.stdin.write(editor.getText());
      process.stdin.end();

But in stdout, I'm only getting: "Broken 1 paths."

Actually, it looks _my_ problem was solved by passing shell=true to child_process. You can keep this issue open if you wish to add this functionality.

I think you just need to find a different approach for accumulating the stdout from isort, I've never done this kind of JS task before but my first attempt worked:

var spawn = require('child_process').spawn,
    child = spawn('isort', ["-"]);

child.stdin.setEncoding('utf-8');

stdout = ''
child.stdout.on('data', function (data) {
    stdout += data
});

child.stdin.write("import b\nimport a\n");
child.stdin.end();

console.log("stdout:", stdout);

Glad to hear you were able to find a solution! If you run into any other snags let me know! And if you publish your plugin I'll make sure to integrate it into the isort documentation

Thanks for putting in the time to write code in both py & js :) 馃

Hey, I've added a link to my package: https://atom.io/packages/formatters-python in the wiki. Hope that is okay :)

Was this page helpful?
0 / 5 - 0 ratings