1"""Convert a NT pathname to a file URL and vice versa. 2 3This module only exists to provide OS-specific code 4for urllib.requests, thus do not use directly. 5""" 6# Testing is done through test_urllib. 7 8def url2pathname(url): 9 """OS-specific conversion from a relative URL of the 'file' scheme 10 to a file system path; not recommended for general use.""" 11 # e.g. 12 # ///C|/foo/bar/spam.foo 13 # and 14 # ///C:/foo/bar/spam.foo 15 # become 16 # C:\foo\bar\spam.foo 17 import string, urllib.parse 18 if url[:3] == '///': 19 # URL has an empty authority section, so the path begins on the third 20 # character. 21 url = url[2:] 22 elif url[:12] == '//localhost/': 23 # Skip past 'localhost' authority. 24 url = url[11:] 25 if url[:3] == '///': 26 # Skip past extra slash before UNC drive in URL path. 27 url = url[1:] 28 # Windows itself uses ":" even in URLs. 29 url = url.replace(':', '|') 30 if not '|' in url: 31 # No drive specifier, just convert slashes 32 # make sure not to convert quoted slashes :-) 33 return urllib.parse.unquote(url.replace('/', '\\')) 34 comp = url.split('|') 35 if len(comp) != 2 or comp[0][-1] not in string.ascii_letters: 36 error = 'Bad URL: ' + url 37 raise OSError(error) 38 drive = comp[0][-1].upper() 39 tail = urllib.parse.unquote(comp[1].replace('/', '\\')) 40 return drive + ':' + tail 41 42def pathname2url(p): 43 """OS-specific conversion from a file system path to a relative URL 44 of the 'file' scheme; not recommended for general use.""" 45 # e.g. 46 # C:\foo\bar\spam.foo 47 # becomes 48 # ///C:/foo/bar/spam.foo 49 import urllib.parse 50 # First, clean up some special forms. We are going to sacrifice 51 # the additional information anyway 52 p = p.replace('\\', '/') 53 if p[:4] == '//?/': 54 p = p[4:] 55 if p[:4].upper() == 'UNC/': 56 p = '//' + p[4:] 57 elif p[1:2] != ':': 58 raise OSError('Bad path: ' + p) 59 if not ':' in p: 60 # No DOS drive specified, just quote the pathname 61 return urllib.parse.quote(p) 62 comp = p.split(':', maxsplit=2) 63 if len(comp) != 2 or len(comp[0]) > 1: 64 error = 'Bad path: ' + p 65 raise OSError(error) 66 67 drive = urllib.parse.quote(comp[0].upper()) 68 tail = urllib.parse.quote(comp[1]) 69 return '///' + drive + ':' + tail 70