from __future__ import absolute_import
import sys
import subprocess
import threading

import six

queue = six.moves.queue


def enqueue_lines(stream, queue):
    for line in iter(stream.readline, b''):
        queue.put(line)
    stream.close()


def Popen_nonblocking(*args, **kwargs):
    """
    Open a subprocess without blocking. Return a process handle with any
    output streams replaced by queues of lines from that stream.

    Usage::

        proc = Popen_nonblocking(..., stdout=subprocess.PIPE)
        try:
            out_line = proc.stdout.get_nowait()
        except queue.Empty:
            "no output available"
        else:
            handle_output(out_line)
    """
    kwargs.setdefault('close_fds', 'posix' in sys.builtin_module_names)
    kwargs.setdefault('bufsize', 1)
    proc = subprocess.Popen(*args, **kwargs)
    if proc.stdout:
        q = queue.Queue()
        t = threading.Thread(target=enqueue_lines, args=(proc.stdout, q))
        proc.stdout = q
        # thread dies with the parent
        t.daemon = True
        t.start()
    if proc.stderr:
        q = queue.Queue()
        t = threading.Thread(target=enqueue_lines, args=(proc.stderr, q))
        proc.stderr = q
        t.daemon = True
        t.start()
    return proc
