Split authority into component parts.  This function supports
    IP-literal as defined in RFC 3986.

    >>> split_authority("user:passwd@host:port")
    ('user', 'passwd', 'host', 'port')
    >>> split_authority("user:@host:port")
    ('user', None, 'host', 'port')
    >>> split_authority("user@host:port")
    ('user', None, 'host', 'port')
    >>> split_authority("user@[host]:port")
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "<stdin>", line 26, in split_authority
    InvalidIPLiteralError: Highly invalid IP-literal detected in URI authority 'user@[host]:port'
    >>> split_authority("user@[::dead:192.168.42.131]:port")
    ('user', None, '[::dead:192.168.42.131]', 'port')
    >>> split_authority("[::dead:192.168.42.131]:port")
    (None, None, '[::dead:192.168.42.131]', 'port')
    >>> split_authority(":port")
    (None, None, None, 'port')
    >>> split_authority("user@:port")
    ('user', None, None, 'port')

    Very basic validation is done if the host part of the authority starts
    with an '[' as when this is the case, the splitting is done in a quite
    different manner than the one used by most URI parsers.  As a result an
    InvalidIPLiteralError exception is raised if IP-literal is patently
    wrong, so the risk of major clashes between two deviant implementations
    is highly reduced.

def split_authority(authority):
    """
    Split authority into component parts.  This function supports
    IP-literal as defined in RFC 3986.

    >>> split_authority("user:passwd@host:port")
    ('user', 'passwd', 'host', 'port')
    >>> split_authority("user:@host:port")
    ('user', None, 'host', 'port')
    >>> split_authority("user@host:port")
    ('user', None, 'host', 'port')
    >>> split_authority("user@[host]:port")
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "<stdin>", line 26, in split_authority
    InvalidIPLiteralError: Highly invalid IP-literal detected in URI authority 'user@[host]:port'
    >>> split_authority("user@[::dead:192.168.42.131]:port")
    ('user', None, '[::dead:192.168.42.131]', 'port')
    >>> split_authority("[::dead:192.168.42.131]:port")
    (None, None, '[::dead:192.168.42.131]', 'port')
    >>> split_authority(":port")
    (None, None, None, 'port')
    >>> split_authority("user@:port")
    ('user', None, None, 'port')

    Very basic validation is done if the host part of the authority starts
    with an '[' as when this is the case, the splitting is done in a quite
    different manner than the one used by most URI parsers.  As a result an
    InvalidIPLiteralError exception is raised if IP-literal is patently
    wrong, so the risk of major clashes between two deviant implementations
    is highly reduced.
    """
    if '@' in authority:
        userinfo, hostport = authority.split('@', 1)
        if userinfo and ':' in userinfo:
            user, passwd = userinfo.split(':', 1)
        else:
            user, passwd = userinfo, None
    else:
        user, passwd, hostport = None, None, authority
    if hostport:
        if hostport[0] == '[':
            m = re.match(r"\[([\da-fA-F:\.]+|" + IPV_FUTURE_RE
                                 + r")\](\:.*|)$", hostport)
            if m:
                host = '[' + m.group(1) + ']'
                port = m.group(2)[1:]
            else:
                raise InvalidIPLiteralError, "Highly invalid IP-literal detected in URI authority %r" % (authority,)
        elif ':' in hostport:
            host, port = hostport.split(':', 1)
        else:
            host, port = hostport, None
    else:
        host, port = None, None
    return (user or None, passwd or None, host or None, port or None)