]>
Commit | Line | Data |
---|---|---|
e0df8241 JR |
1 | import os |
2 | import string | |
3 | import urllib.parse | |
4 | import urllib.request | |
5 | from typing import Optional | |
6 | ||
7 | from .compat import WINDOWS | |
8 | ||
9 | ||
10 | def get_url_scheme(url: str) -> Optional[str]: | |
11 | if ":" not in url: | |
12 | return None | |
13 | return url.split(":", 1)[0].lower() | |
14 | ||
15 | ||
16 | def path_to_url(path: str) -> str: | |
17 | """ | |
18 | Convert a path to a file: URL. The path will be made absolute and have | |
19 | quoted path parts. | |
20 | """ | |
21 | path = os.path.normpath(os.path.abspath(path)) | |
22 | url = urllib.parse.urljoin("file:", urllib.request.pathname2url(path)) | |
23 | return url | |
24 | ||
25 | ||
26 | def url_to_path(url: str) -> str: | |
27 | """ | |
28 | Convert a file: URL to a path. | |
29 | """ | |
30 | assert url.startswith( | |
31 | "file:" | |
32 | ), f"You can only turn file: urls into filenames (not {url!r})" | |
33 | ||
34 | _, netloc, path, _, _ = urllib.parse.urlsplit(url) | |
35 | ||
36 | if not netloc or netloc == "localhost": | |
37 | # According to RFC 8089, same as empty authority. | |
38 | netloc = "" | |
39 | elif WINDOWS: | |
40 | # If we have a UNC path, prepend UNC share notation. | |
41 | netloc = "\\\\" + netloc | |
42 | else: | |
43 | raise ValueError( | |
44 | f"non-local file URIs are not supported on this platform: {url!r}" | |
45 | ) | |
46 | ||
47 | path = urllib.request.url2pathname(netloc + path) | |
48 | ||
49 | # On Windows, urlsplit parses the path as something like "/C:/Users/foo". | |
50 | # This creates issues for path-related functions like io.open(), so we try | |
51 | # to detect and strip the leading slash. | |
52 | if ( | |
53 | WINDOWS | |
54 | and not netloc # Not UNC. | |
55 | and len(path) >= 3 | |
56 | and path[0] == "/" # Leading slash to strip. | |
57 | and path[1] in string.ascii_letters # Drive letter. | |
58 | and path[2:4] in (":", ":/") # Colon + end of string, or colon + absolute path. | |
59 | ): | |
60 | path = path[1:] | |
61 | ||
62 | return path |