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.

appdirs.py 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. """
  2. This code was taken from https://github.com/ActiveState/appdirs and modified
  3. to suit our purposes.
  4. """
  5. from __future__ import absolute_import
  6. import os
  7. import sys
  8. from pip._vendor.six import PY2, text_type
  9. from pip._internal.utils.compat import WINDOWS, expanduser
  10. from pip._internal.utils.typing import MYPY_CHECK_RUNNING
  11. if MYPY_CHECK_RUNNING:
  12. from typing import ( # noqa: F401
  13. List, Union
  14. )
  15. def user_cache_dir(appname):
  16. # type: (str) -> str
  17. r"""
  18. Return full path to the user-specific cache dir for this application.
  19. "appname" is the name of application.
  20. Typical user cache directories are:
  21. macOS: ~/Library/Caches/<AppName>
  22. Unix: ~/.cache/<AppName> (XDG default)
  23. Windows: C:\Users\<username>\AppData\Local\<AppName>\Cache
  24. On Windows the only suggestion in the MSDN docs is that local settings go
  25. in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the
  26. non-roaming app data dir (the default returned by `user_data_dir`). Apps
  27. typically put cache data somewhere *under* the given dir here. Some
  28. examples:
  29. ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
  30. ...\Acme\SuperApp\Cache\1.0
  31. OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
  32. """
  33. if WINDOWS:
  34. # Get the base path
  35. path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
  36. # When using Python 2, return paths as bytes on Windows like we do on
  37. # other operating systems. See helper function docs for more details.
  38. if PY2 and isinstance(path, text_type):
  39. path = _win_path_to_bytes(path)
  40. # Add our app name and Cache directory to it
  41. path = os.path.join(path, appname, "Cache")
  42. elif sys.platform == "darwin":
  43. # Get the base path
  44. path = expanduser("~/Library/Caches")
  45. # Add our app name to it
  46. path = os.path.join(path, appname)
  47. else:
  48. # Get the base path
  49. path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache"))
  50. # Add our app name to it
  51. path = os.path.join(path, appname)
  52. return path
  53. def user_data_dir(appname, roaming=False):
  54. # type: (str, bool) -> str
  55. r"""
  56. Return full path to the user-specific data dir for this application.
  57. "appname" is the name of application.
  58. If None, just the system directory is returned.
  59. "roaming" (boolean, default False) can be set True to use the Windows
  60. roaming appdata directory. That means that for users on a Windows
  61. network setup for roaming profiles, this user data will be
  62. sync'd on login. See
  63. <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
  64. for a discussion of issues.
  65. Typical user data directories are:
  66. macOS: ~/Library/Application Support/<AppName>
  67. if it exists, else ~/.config/<AppName>
  68. Unix: ~/.local/share/<AppName> # or in
  69. $XDG_DATA_HOME, if defined
  70. Win XP (not roaming): C:\Documents and Settings\<username>\ ...
  71. ...Application Data\<AppName>
  72. Win XP (roaming): C:\Documents and Settings\<username>\Local ...
  73. ...Settings\Application Data\<AppName>
  74. Win 7 (not roaming): C:\\Users\<username>\AppData\Local\<AppName>
  75. Win 7 (roaming): C:\\Users\<username>\AppData\Roaming\<AppName>
  76. For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
  77. That means, by default "~/.local/share/<AppName>".
  78. """
  79. if WINDOWS:
  80. const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
  81. path = os.path.join(os.path.normpath(_get_win_folder(const)), appname)
  82. elif sys.platform == "darwin":
  83. path = os.path.join(
  84. expanduser('~/Library/Application Support/'),
  85. appname,
  86. ) if os.path.isdir(os.path.join(
  87. expanduser('~/Library/Application Support/'),
  88. appname,
  89. )
  90. ) else os.path.join(
  91. expanduser('~/.config/'),
  92. appname,
  93. )
  94. else:
  95. path = os.path.join(
  96. os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")),
  97. appname,
  98. )
  99. return path
  100. def user_config_dir(appname, roaming=True):
  101. # type: (str, bool) -> str
  102. """Return full path to the user-specific config dir for this application.
  103. "appname" is the name of application.
  104. If None, just the system directory is returned.
  105. "roaming" (boolean, default True) can be set False to not use the
  106. Windows roaming appdata directory. That means that for users on a
  107. Windows network setup for roaming profiles, this user data will be
  108. sync'd on login. See
  109. <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
  110. for a discussion of issues.
  111. Typical user data directories are:
  112. macOS: same as user_data_dir
  113. Unix: ~/.config/<AppName>
  114. Win *: same as user_data_dir
  115. For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
  116. That means, by default "~/.config/<AppName>".
  117. """
  118. if WINDOWS:
  119. path = user_data_dir(appname, roaming=roaming)
  120. elif sys.platform == "darwin":
  121. path = user_data_dir(appname)
  122. else:
  123. path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config"))
  124. path = os.path.join(path, appname)
  125. return path
  126. # for the discussion regarding site_config_dirs locations
  127. # see <https://github.com/pypa/pip/issues/1733>
  128. def site_config_dirs(appname):
  129. # type: (str) -> List[str]
  130. r"""Return a list of potential user-shared config dirs for this application.
  131. "appname" is the name of application.
  132. Typical user config directories are:
  133. macOS: /Library/Application Support/<AppName>/
  134. Unix: /etc or $XDG_CONFIG_DIRS[i]/<AppName>/ for each value in
  135. $XDG_CONFIG_DIRS
  136. Win XP: C:\Documents and Settings\All Users\Application ...
  137. ...Data\<AppName>\
  138. Vista: (Fail! "C:\ProgramData" is a hidden *system* directory
  139. on Vista.)
  140. Win 7: Hidden, but writeable on Win 7:
  141. C:\ProgramData\<AppName>\
  142. """
  143. if WINDOWS:
  144. path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
  145. pathlist = [os.path.join(path, appname)]
  146. elif sys.platform == 'darwin':
  147. pathlist = [os.path.join('/Library/Application Support', appname)]
  148. else:
  149. # try looking in $XDG_CONFIG_DIRS
  150. xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
  151. if xdg_config_dirs:
  152. pathlist = [
  153. os.path.join(expanduser(x), appname)
  154. for x in xdg_config_dirs.split(os.pathsep)
  155. ]
  156. else:
  157. pathlist = []
  158. # always look in /etc directly as well
  159. pathlist.append('/etc')
  160. return pathlist
  161. # -- Windows support functions --
  162. def _get_win_folder_from_registry(csidl_name):
  163. # type: (str) -> str
  164. """
  165. This is a fallback technique at best. I'm not sure if using the
  166. registry for this guarantees us the correct answer for all CSIDL_*
  167. names.
  168. """
  169. import _winreg
  170. shell_folder_name = {
  171. "CSIDL_APPDATA": "AppData",
  172. "CSIDL_COMMON_APPDATA": "Common AppData",
  173. "CSIDL_LOCAL_APPDATA": "Local AppData",
  174. }[csidl_name]
  175. key = _winreg.OpenKey(
  176. _winreg.HKEY_CURRENT_USER,
  177. r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
  178. )
  179. directory, _type = _winreg.QueryValueEx(key, shell_folder_name)
  180. return directory
  181. def _get_win_folder_with_ctypes(csidl_name):
  182. # type: (str) -> str
  183. csidl_const = {
  184. "CSIDL_APPDATA": 26,
  185. "CSIDL_COMMON_APPDATA": 35,
  186. "CSIDL_LOCAL_APPDATA": 28,
  187. }[csidl_name]
  188. buf = ctypes.create_unicode_buffer(1024)
  189. ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
  190. # Downgrade to short path name if have highbit chars. See
  191. # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
  192. has_high_char = False
  193. for c in buf:
  194. if ord(c) > 255:
  195. has_high_char = True
  196. break
  197. if has_high_char:
  198. buf2 = ctypes.create_unicode_buffer(1024)
  199. if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
  200. buf = buf2
  201. return buf.value
  202. if WINDOWS:
  203. try:
  204. import ctypes
  205. _get_win_folder = _get_win_folder_with_ctypes
  206. except ImportError:
  207. _get_win_folder = _get_win_folder_from_registry
  208. def _win_path_to_bytes(path):
  209. """Encode Windows paths to bytes. Only used on Python 2.
  210. Motivation is to be consistent with other operating systems where paths
  211. are also returned as bytes. This avoids problems mixing bytes and Unicode
  212. elsewhere in the codebase. For more details and discussion see
  213. <https://github.com/pypa/pip/issues/3463>.
  214. If encoding using ASCII and MBCS fails, return the original Unicode path.
  215. """
  216. for encoding in ('ASCII', 'MBCS'):
  217. try:
  218. return path.encode(encoding)
  219. except (UnicodeEncodeError, LookupError):
  220. pass
  221. return path