@@ -45,9 +45,10 @@ def filepath_from_url(urlstr):
45
45
Take an url and return a filepath.
46
46
47
47
URLs can either be encoded according to the `RFC 3986`_ standard or not.
48
- Additionally, Windows mapped paths need to be accounted for when processing a
49
- URL; however, there are `ongoing discussions`_ about how to best handle this within
50
- Python. This function is meant to cover all of these scenarios in the interim.
48
+ Additionally, Windows mapped drive letter and UNC paths need to be accounted for
49
+ when processing URL(s); however, there are `ongoing discussions`_ about how to best
50
+ handle this within Python developer community. This function is meant to cover
51
+ these scenarios in the interim.
51
52
52
53
.. _RFC 3986: https://tools.ietf.org/html/rfc3986#section-2.1
53
54
.. _ongoing discussions: https://discuss.python.org/t/file-uris-in-python/15600
@@ -56,17 +57,38 @@ def filepath_from_url(urlstr):
56
57
# Parse provided URL
57
58
parsed_result = urlparse .urlparse (urlstr )
58
59
60
+ # De-encode the parsed path
61
+ decoded_parsed_path = urlparse .unquote (parsed_result .path )
62
+
59
63
# Convert the parsed URL to a path
60
- filepath = PurePath (request .url2pathname (parsed_result . path ))
64
+ filepath = PurePath (request .url2pathname (decoded_parsed_path ))
61
65
62
66
# If the network location is a window drive, reassemble the path
63
67
if PureWindowsPath (parsed_result .netloc ).drive :
64
- filepath = PurePath (parsed_result .netloc + parsed_result .path )
68
+ filepath = PurePath (parsed_result .netloc + decoded_parsed_path )
69
+
70
+ # If the specified index is a windows drive, then append it to the other parts
71
+ elif PureWindowsPath (filepath .parts [0 ]).drive :
72
+ filepath = PurePosixPath (filepath .drive , * filepath .parts [1 :])
65
73
66
- # Otherwise check if the specified index is a windows drive, then offset the path
74
+ # If the specified index is a windows drive, then offset the path
67
75
elif PureWindowsPath (filepath .parts [1 ]).drive :
68
76
# Remove leading "/" if/when `request.url2pathname` yields "/S:/path/file.ext"
69
77
filepath = PurePosixPath (* filepath .parts [1 :])
70
78
79
+ # Should catch UNC paths,
80
+ # as parsing "file:///some/path/to/file.ext" doesn't provide a netloc
81
+ elif parsed_result .netloc and parsed_result .netloc != 'localhost' :
82
+ # Paths of type: "file://host/share/path/to/file.ext" provide "host" as netloc
83
+ filepath = PurePath ('//' , parsed_result .netloc + decoded_parsed_path )
84
+
85
+ # Executing `as_posix` on Windows seems to generate a path with only
86
+ # 1 leading `/`, so we insert another `/` at the front of the string path
87
+ # to match Linux and Windows UNC conventions and return it.
88
+ conformed_filepath = filepath .as_posix ()
89
+ if not conformed_filepath .startswith ('//' ):
90
+ conformed_filepath = '/' + conformed_filepath
91
+ return conformed_filepath
92
+
71
93
# Convert "\" to "/" if needed
72
94
return filepath .as_posix ()
0 commit comments