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.0 KiB

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