def fsn2uri(path):
    """
    Args:
        path (fsnative): The path to convert to an URI
    Returns:
        `text`: An ASCII only URI
    Raises:
        TypeError: If no `fsnative` was passed
        ValueError: If the path can't be converted

    Takes a `fsnative` path and returns a file URI.

    On Windows non-ASCII characters will be encoded using utf-8 and then
    percent encoded.
    """

    path = _fsn2native(path)

    def _quote_path(path):
        # RFC 2396
        path = quote(path, "/:@&=+$,")
        if PY2:
            path = path.decode("ascii")
        return path

    if is_win:
        buf = ctypes.create_unicode_buffer(winapi.INTERNET_MAX_URL_LENGTH)
        length = winapi.DWORD(winapi.INTERNET_MAX_URL_LENGTH)
        flags = 0
        try:
            winapi.UrlCreateFromPathW(path, buf, ctypes.byref(length), flags)
        except WindowsError as e:
            raise ValueError(e)
        uri = buf[:length.value]

        # For some reason UrlCreateFromPathW escapes some chars outside of
        # ASCII and some not. Unquote and re-quote with utf-8.
        if PY3:
            # latin-1 maps code points directly to bytes, which is what we want
            uri = unquote(uri, "latin-1")
        else:
            # Python 2 does what we want by default
            uri = unquote(uri)

        return _quote_path(uri.encode("utf-8", _surrogatepass))

    else:
        return u"file://" + _quote_path(path)
Args:
        path (fsnative): The path to convert to an URI
    Returns:
        `text`: An ASCII only URI
    Raises:
        TypeError: If no `fsnative` was passed
        ValueError: If the path can't be converted

    Takes a `fsnative` path and returns a file URI.

    On Windows non-ASCII characters will be encoded using utf-8 and then
    percent encoded.