nturl2path.py 2.3 KB

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