Starts a manhole server on a given TCP and/or UNIX address.

    Keyword arguments:
        banner - Text to display when client initially connects.
        host - interface to bind on.
        port - port to listen on over TCP. Default is disabled.
        path - filesystem path to listen on over UNIX sockets. Deafult is disabled.
        namespace - dictionary namespace to provide to connected clients.
        threaded - if True, use a threaded interpreter. False, run them in the
                   middle of the event loop. See ThreadedInteractiveInterpreter
                   for details.
        command_timeout - timeout in seconds for commands. Only applies if
                          `threaded` is True.
        shared - If True, share a single namespace between all clients.

    Returns a Future for starting the server(s).

def start_manhole(banner=None, host='127.0.0.1', port=None, path=None,
        namespace=None, loop=None, threaded=False, command_timeout=5,
        shared=False):

    """Starts a manhole server on a given TCP and/or UNIX address.

    Keyword arguments:
        banner - Text to display when client initially connects.
        host - interface to bind on.
        port - port to listen on over TCP. Default is disabled.
        path - filesystem path to listen on over UNIX sockets. Deafult is disabled.
        namespace - dictionary namespace to provide to connected clients.
        threaded - if True, use a threaded interpreter. False, run them in the
                   middle of the event loop. See ThreadedInteractiveInterpreter
                   for details.
        command_timeout - timeout in seconds for commands. Only applies if
                          `threaded` is True.
        shared - If True, share a single namespace between all clients.

    Returns a Future for starting the server(s).
    """

    loop = loop or asyncio.get_event_loop()

    if (port, path) == (None, None):
        raise ValueError('At least one of port or path must be given')

    if threaded:
        interpreter_class = functools.partial(
            ThreadedInteractiveInterpreter, command_timeout=command_timeout)
    else:
        interpreter_class = InteractiveInterpreter

    client_cb = InterpreterFactory(
        interpreter_class, shared=shared, namespace=namespace, banner=banner,
        loop=loop)

    coros = []

    if path:
        f = asyncio.ensure_future(
            asyncio.start_unix_server(client_cb, path=path, loop=loop))
        coros.append(f)

    if port:
        f = asyncio.ensure_future(asyncio.start_server(
            client_cb, host=host, port=port, loop=loop), loop=loop)
        coros.append(f)

    return asyncio.gather(*coros, loop=loop)