from asyncio import events
from asyncio import protocols
from asyncio import streams
from asyncio import transports
from asyncio.coroutines import coroutine
from typing import Any, AnyStr, Generator, List, Optional, Tuple, Union, IO

__all__: List[str]

PIPE = ...  # type: int
STDOUT = ...  # type: int
DEVNULL = ...  # type: int

class SubprocessStreamProtocol(streams.FlowControlMixin,
                               protocols.SubprocessProtocol):
    stdin = ...  # type: Optional[streams.StreamWriter]
    stdout = ...  # type: Optional[streams.StreamReader]
    stderr = ...  # type: Optional[streams.StreamReader]
    def __init__(self, limit: int, loop: events.AbstractEventLoop) -> None: ...
    def connection_made(self, transport: transports.BaseTransport) -> None: ...
    def pipe_data_received(self, fd: int, data: AnyStr) -> None: ...
    def pipe_connection_lost(self, fd: int, exc: Exception) -> None: ...
    def process_exited(self) -> None: ...


class Process:
    stdin = ...  # type: Optional[streams.StreamWriter]
    stdout = ...  # type: Optional[streams.StreamReader]
    stderr = ...  # type: Optional[streams.StreamReader]
    pid = ...  # type: int
    def __init__(self,
            transport: transports.BaseTransport,
            protocol: protocols.BaseProtocol,
            loop: events.AbstractEventLoop) -> None: ...
    @property
    def returncode(self) -> int: ...
    @coroutine
    def wait(self) -> Generator[Any, None, int]: ...
    def send_signal(self, signal: int) -> None: ...
    def terminate(self) -> None: ...
    def kill(self) -> None: ...
    @coroutine
    def communicate(self, input: Optional[bytes] = ...) -> Generator[Any, None, Tuple[bytes, bytes]]: ...


@coroutine
def create_subprocess_shell(
    *Args: Union[str, bytes],  # Union used instead of AnyStr due to mypy issue  #1236
    stdin: Union[int, IO[Any], None] = ...,
    stdout: Union[int, IO[Any], None] = ...,
    stderr: Union[int, IO[Any], None] = ...,
    loop: events.AbstractEventLoop = ...,
    limit: int = ...,
    **kwds: Any
) -> Generator[Any, None, Process]: ...

@coroutine
def create_subprocess_exec(
    program: Union[str, bytes],  # Union used instead of AnyStr due to mypy issue  #1236
    *args: Any,
    stdin: Union[int, IO[Any], None] = ...,
    stdout: Union[int, IO[Any], None] = ...,
    stderr: Union[int, IO[Any], None] = ...,
    loop: events.AbstractEventLoop = ...,
    limit: int = ...,
    **kwds: Any
) -> Generator[Any, None, Process]: ...
