You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

117 lines
3.3 KiB

  1. """Stuff that differs in different Python versions and platform
  2. distributions."""
  3. from __future__ import absolute_import, division
  4. import os
  5. import sys
  6. from pip._vendor.six import text_type
  7. try:
  8. from logging.config import dictConfig as logging_dictConfig
  9. except ImportError:
  10. from pip.compat.dictconfig import dictConfig as logging_dictConfig
  11. try:
  12. import ipaddress
  13. except ImportError:
  14. try:
  15. from pip._vendor import ipaddress
  16. except ImportError:
  17. import ipaddr as ipaddress
  18. ipaddress.ip_address = ipaddress.IPAddress
  19. ipaddress.ip_network = ipaddress.IPNetwork
  20. __all__ = [
  21. "logging_dictConfig", "ipaddress", "uses_pycache", "console_to_str",
  22. "native_str", "get_path_uid", "stdlib_pkgs", "WINDOWS",
  23. ]
  24. if sys.version_info >= (3, 4):
  25. uses_pycache = True
  26. from importlib.util import cache_from_source
  27. else:
  28. import imp
  29. uses_pycache = hasattr(imp, 'cache_from_source')
  30. if uses_pycache:
  31. cache_from_source = imp.cache_from_source
  32. else:
  33. cache_from_source = None
  34. if sys.version_info >= (3,):
  35. def console_to_str(s):
  36. try:
  37. return s.decode(sys.__stdout__.encoding)
  38. except UnicodeDecodeError:
  39. return s.decode('utf_8')
  40. def native_str(s, replace=False):
  41. if isinstance(s, bytes):
  42. return s.decode('utf-8', 'replace' if replace else 'strict')
  43. return s
  44. else:
  45. def console_to_str(s):
  46. return s
  47. def native_str(s, replace=False):
  48. # Replace is ignored -- unicode to UTF-8 can't fail
  49. if isinstance(s, text_type):
  50. return s.encode('utf-8')
  51. return s
  52. def total_seconds(td):
  53. if hasattr(td, "total_seconds"):
  54. return td.total_seconds()
  55. else:
  56. val = td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6
  57. return val / 10 ** 6
  58. def get_path_uid(path):
  59. """
  60. Return path's uid.
  61. Does not follow symlinks:
  62. https://github.com/pypa/pip/pull/935#discussion_r5307003
  63. Placed this function in compat due to differences on AIX and
  64. Jython, that should eventually go away.
  65. :raises OSError: When path is a symlink or can't be read.
  66. """
  67. if hasattr(os, 'O_NOFOLLOW'):
  68. fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
  69. file_uid = os.fstat(fd).st_uid
  70. os.close(fd)
  71. else: # AIX and Jython
  72. # WARNING: time of check vulnerabity, but best we can do w/o NOFOLLOW
  73. if not os.path.islink(path):
  74. # older versions of Jython don't have `os.fstat`
  75. file_uid = os.stat(path).st_uid
  76. else:
  77. # raise OSError for parity with os.O_NOFOLLOW above
  78. raise OSError(
  79. "%s is a symlink; Will not return uid for symlinks" % path
  80. )
  81. return file_uid
  82. # packages in the stdlib that may have installation metadata, but should not be
  83. # considered 'installed'. this theoretically could be determined based on
  84. # dist.location (py27:`sysconfig.get_paths()['stdlib']`,
  85. # py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may
  86. # make this ineffective, so hard-coding
  87. stdlib_pkgs = ['python', 'wsgiref']
  88. if sys.version_info >= (2, 7):
  89. stdlib_pkgs.extend(['argparse'])
  90. # windows detection, covers cpython and ironpython
  91. WINDOWS = (sys.platform.startswith("win") or
  92. (sys.platform == 'cli' and os.name == 'nt'))