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