Parses the supplied Redis URL and returns a dict with the parsed/split data.

    For ambiguous URLs like redis://localhost and redis://my_socket_file this function will prioritize network URLs over
    socket URLs. redis://my_socket_file will be interpreted as a network URL, with the Redis server having a hostname of
    'my_socket_file'. Use the file:// or redis+socket:// (Celery compatibility) URL scheme to force socket URL
    interpretations over network URLs.

    Positional arguments:
    url -- URL to redis server. Examples are in this file's Redis class docstring under REDIS_URL.

    Returns:
    Dictionary with parsed data, compatible with StrictRedis.__init__() keyword arguments.

    Raises:
    ValueError -- if the supplies URL was malformed or invalid.

def parse_url(url):
    """Parses the supplied Redis URL and returns a dict with the parsed/split data.

    For ambiguous URLs like redis://localhost and redis://my_socket_file this function will prioritize network URLs over
    socket URLs. redis://my_socket_file will be interpreted as a network URL, with the Redis server having a hostname of
    'my_socket_file'. Use the file:// or redis+socket:// (Celery compatibility) URL scheme to force socket URL
    interpretations over network URLs.

    Positional arguments:
    url -- URL to redis server. Examples are in this file's Redis class docstring under REDIS_URL.

    Returns:
    Dictionary with parsed data, compatible with StrictRedis.__init__() keyword arguments.

    Raises:
    ValueError -- if the supplies URL was malformed or invalid.
    """
    # Parse URL, make sure string is valid.
    try:
        split = urlsplit(url.rstrip('/'))
    except (AttributeError, TypeError) as e:
        raise ValueError('Malformed URL specified: {0}'.format(e))
    if split.scheme not in ['redis+socket', 'redis', 'file']:
        raise ValueError('Malformed URL specified.')
    scheme = split.scheme
    netloc = split.netloc
    hostname = split.hostname
    path = split.path
    password = split.password
    try:
        port = split.port
    except ValueError:
        port = None  # Stupid urlsplit bug on Windows.

    # urlsplit sucks on Windows, work around this.
    if os.name == 'nt' and not path and '\\' in netloc:
        if '@' in netloc:
            position = netloc.find('@') + 1
            path = netloc[position:]
            netloc = netloc[:position]
        else:
            path = netloc
            netloc = ''

    # Handle non-socket URLs.
    if scheme == 'redis' and netloc and not netloc.endswith('.') and not netloc.endswith('@'):
        result = dict(host=hostname)
        if password:
            result['password'] = password
        if port:
            result['port'] = port
        if path:
            if not path[1:].isdigit():
                raise ValueError('Network URL path has non-digit characters: {0}'.format(path[1:]))
            result['db'] = int(path[1:])
        return result

    # Handle socket URLs.
    if port:
        raise ValueError('Socket URL looks like non-socket URL.')
    if not password:
        socket_path = '{0}{1}'.format(netloc, path)
    elif netloc.endswith('.'):
        socket_path = '{0}{1}'.format(netloc.split('@')[1], path)
    elif not path:
        socket_path = netloc.split('@')[1]
    else:
        socket_path = path

    # Catch bad paths.
    parent_dir = os.path.split(socket_path)[0]
    if parent_dir and not os.path.isdir(parent_dir):
        raise ValueError("Unix socket path's parent not a dir: {0}".format(parent_dir))

    # Finish up.
    result = dict(unix_socket_path=socket_path)
    if password:
        result['password'] = password
    return result