Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/pip/_vendor/appdirs.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: utf-8 -*- | |
3 # Copyright (c) 2005-2010 ActiveState Software Inc. | |
4 # Copyright (c) 2013 Eddy Petrișor | |
5 | |
6 """Utilities for determining application-specific dirs. | |
7 | |
8 See <http://github.com/ActiveState/appdirs> for details and usage. | |
9 """ | |
10 # Dev Notes: | |
11 # - MSDN on where to store app data files: | |
12 # http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 | |
13 # - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html | |
14 # - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html | |
15 | |
16 __version__ = "1.4.4" | |
17 __version_info__ = tuple(int(segment) for segment in __version__.split(".")) | |
18 | |
19 | |
20 import sys | |
21 import os | |
22 | |
23 PY3 = sys.version_info[0] == 3 | |
24 | |
25 if PY3: | |
26 unicode = str | |
27 | |
28 if sys.platform.startswith('java'): | |
29 import platform | |
30 os_name = platform.java_ver()[3][0] | |
31 if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. | |
32 system = 'win32' | |
33 elif os_name.startswith('Mac'): # "Mac OS X", etc. | |
34 system = 'darwin' | |
35 else: # "Linux", "SunOS", "FreeBSD", etc. | |
36 # Setting this to "linux2" is not ideal, but only Windows or Mac | |
37 # are actually checked for and the rest of the module expects | |
38 # *sys.platform* style strings. | |
39 system = 'linux2' | |
40 elif sys.platform == 'cli' and os.name == 'nt': | |
41 # Detect Windows in IronPython to match pip._internal.utils.compat.WINDOWS | |
42 # Discussion: <https://github.com/pypa/pip/pull/7501> | |
43 system = 'win32' | |
44 else: | |
45 system = sys.platform | |
46 | |
47 | |
48 | |
49 def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): | |
50 r"""Return full path to the user-specific data dir for this application. | |
51 | |
52 "appname" is the name of application. | |
53 If None, just the system directory is returned. | |
54 "appauthor" (only used on Windows) is the name of the | |
55 appauthor or distributing body for this application. Typically | |
56 it is the owning company name. This falls back to appname. You may | |
57 pass False to disable it. | |
58 "version" is an optional version path element to append to the | |
59 path. You might want to use this if you want multiple versions | |
60 of your app to be able to run independently. If used, this | |
61 would typically be "<major>.<minor>". | |
62 Only applied when appname is present. | |
63 "roaming" (boolean, default False) can be set True to use the Windows | |
64 roaming appdata directory. That means that for users on a Windows | |
65 network setup for roaming profiles, this user data will be | |
66 sync'd on login. See | |
67 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> | |
68 for a discussion of issues. | |
69 | |
70 Typical user data directories are: | |
71 Mac OS X: ~/Library/Application Support/<AppName> # or ~/.config/<AppName>, if the other does not exist | |
72 Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined | |
73 Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> | |
74 Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> | |
75 Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> | |
76 Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> | |
77 | |
78 For Unix, we follow the XDG spec and support $XDG_DATA_HOME. | |
79 That means, by default "~/.local/share/<AppName>". | |
80 """ | |
81 if system == "win32": | |
82 if appauthor is None: | |
83 appauthor = appname | |
84 const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" | |
85 path = os.path.normpath(_get_win_folder(const)) | |
86 if appname: | |
87 if appauthor is not False: | |
88 path = os.path.join(path, appauthor, appname) | |
89 else: | |
90 path = os.path.join(path, appname) | |
91 elif system == 'darwin': | |
92 path = os.path.expanduser('~/Library/Application Support/') | |
93 if appname: | |
94 path = os.path.join(path, appname) | |
95 else: | |
96 path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) | |
97 if appname: | |
98 path = os.path.join(path, appname) | |
99 if appname and version: | |
100 path = os.path.join(path, version) | |
101 return path | |
102 | |
103 | |
104 def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): | |
105 r"""Return full path to the user-shared data dir for this application. | |
106 | |
107 "appname" is the name of application. | |
108 If None, just the system directory is returned. | |
109 "appauthor" (only used on Windows) is the name of the | |
110 appauthor or distributing body for this application. Typically | |
111 it is the owning company name. This falls back to appname. You may | |
112 pass False to disable it. | |
113 "version" is an optional version path element to append to the | |
114 path. You might want to use this if you want multiple versions | |
115 of your app to be able to run independently. If used, this | |
116 would typically be "<major>.<minor>". | |
117 Only applied when appname is present. | |
118 "multipath" is an optional parameter only applicable to *nix | |
119 which indicates that the entire list of data dirs should be | |
120 returned. By default, the first item from XDG_DATA_DIRS is | |
121 returned, or '/usr/local/share/<AppName>', | |
122 if XDG_DATA_DIRS is not set | |
123 | |
124 Typical site data directories are: | |
125 Mac OS X: /Library/Application Support/<AppName> | |
126 Unix: /usr/local/share/<AppName> or /usr/share/<AppName> | |
127 Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> | |
128 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) | |
129 Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. | |
130 | |
131 For Unix, this is using the $XDG_DATA_DIRS[0] default. | |
132 | |
133 WARNING: Do not use this on Windows. See the Vista-Fail note above for why. | |
134 """ | |
135 if system == "win32": | |
136 if appauthor is None: | |
137 appauthor = appname | |
138 path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) | |
139 if appname: | |
140 if appauthor is not False: | |
141 path = os.path.join(path, appauthor, appname) | |
142 else: | |
143 path = os.path.join(path, appname) | |
144 elif system == 'darwin': | |
145 path = os.path.expanduser('/Library/Application Support') | |
146 if appname: | |
147 path = os.path.join(path, appname) | |
148 else: | |
149 # XDG default for $XDG_DATA_DIRS | |
150 # only first, if multipath is False | |
151 path = os.getenv('XDG_DATA_DIRS', | |
152 os.pathsep.join(['/usr/local/share', '/usr/share'])) | |
153 pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] | |
154 if appname: | |
155 if version: | |
156 appname = os.path.join(appname, version) | |
157 pathlist = [os.path.join(x, appname) for x in pathlist] | |
158 | |
159 if multipath: | |
160 path = os.pathsep.join(pathlist) | |
161 else: | |
162 path = pathlist[0] | |
163 return path | |
164 | |
165 if appname and version: | |
166 path = os.path.join(path, version) | |
167 return path | |
168 | |
169 | |
170 def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): | |
171 r"""Return full path to the user-specific config dir for this application. | |
172 | |
173 "appname" is the name of application. | |
174 If None, just the system directory is returned. | |
175 "appauthor" (only used on Windows) is the name of the | |
176 appauthor or distributing body for this application. Typically | |
177 it is the owning company name. This falls back to appname. You may | |
178 pass False to disable it. | |
179 "version" is an optional version path element to append to the | |
180 path. You might want to use this if you want multiple versions | |
181 of your app to be able to run independently. If used, this | |
182 would typically be "<major>.<minor>". | |
183 Only applied when appname is present. | |
184 "roaming" (boolean, default False) can be set True to use the Windows | |
185 roaming appdata directory. That means that for users on a Windows | |
186 network setup for roaming profiles, this user data will be | |
187 sync'd on login. See | |
188 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> | |
189 for a discussion of issues. | |
190 | |
191 Typical user config directories are: | |
192 Mac OS X: same as user_data_dir | |
193 Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined | |
194 Win *: same as user_data_dir | |
195 | |
196 For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. | |
197 That means, by default "~/.config/<AppName>". | |
198 """ | |
199 if system in ["win32", "darwin"]: | |
200 path = user_data_dir(appname, appauthor, None, roaming) | |
201 else: | |
202 path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) | |
203 if appname: | |
204 path = os.path.join(path, appname) | |
205 if appname and version: | |
206 path = os.path.join(path, version) | |
207 return path | |
208 | |
209 | |
210 # for the discussion regarding site_config_dir locations | |
211 # see <https://github.com/pypa/pip/issues/1733> | |
212 def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): | |
213 r"""Return full path to the user-shared data dir for this application. | |
214 | |
215 "appname" is the name of application. | |
216 If None, just the system directory is returned. | |
217 "appauthor" (only used on Windows) is the name of the | |
218 appauthor or distributing body for this application. Typically | |
219 it is the owning company name. This falls back to appname. You may | |
220 pass False to disable it. | |
221 "version" is an optional version path element to append to the | |
222 path. You might want to use this if you want multiple versions | |
223 of your app to be able to run independently. If used, this | |
224 would typically be "<major>.<minor>". | |
225 Only applied when appname is present. | |
226 "multipath" is an optional parameter only applicable to *nix | |
227 which indicates that the entire list of config dirs should be | |
228 returned. By default, the first item from XDG_CONFIG_DIRS is | |
229 returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set | |
230 | |
231 Typical site config directories are: | |
232 Mac OS X: same as site_data_dir | |
233 Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in | |
234 $XDG_CONFIG_DIRS | |
235 Win *: same as site_data_dir | |
236 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) | |
237 | |
238 For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False | |
239 | |
240 WARNING: Do not use this on Windows. See the Vista-Fail note above for why. | |
241 """ | |
242 if system in ["win32", "darwin"]: | |
243 path = site_data_dir(appname, appauthor) | |
244 if appname and version: | |
245 path = os.path.join(path, version) | |
246 else: | |
247 # XDG default for $XDG_CONFIG_DIRS (missing or empty) | |
248 # see <https://github.com/pypa/pip/pull/7501#discussion_r360624829> | |
249 # only first, if multipath is False | |
250 path = os.getenv('XDG_CONFIG_DIRS') or '/etc/xdg' | |
251 pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) if x] | |
252 if appname: | |
253 if version: | |
254 appname = os.path.join(appname, version) | |
255 pathlist = [os.path.join(x, appname) for x in pathlist] | |
256 | |
257 if multipath: | |
258 path = os.pathsep.join(pathlist) | |
259 else: | |
260 path = pathlist[0] | |
261 return path | |
262 | |
263 | |
264 def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): | |
265 r"""Return full path to the user-specific cache dir for this application. | |
266 | |
267 "appname" is the name of application. | |
268 If None, just the system directory is returned. | |
269 "appauthor" (only used on Windows) is the name of the | |
270 appauthor or distributing body for this application. Typically | |
271 it is the owning company name. This falls back to appname. You may | |
272 pass False to disable it. | |
273 "version" is an optional version path element to append to the | |
274 path. You might want to use this if you want multiple versions | |
275 of your app to be able to run independently. If used, this | |
276 would typically be "<major>.<minor>". | |
277 Only applied when appname is present. | |
278 "opinion" (boolean) can be False to disable the appending of | |
279 "Cache" to the base app data dir for Windows. See | |
280 discussion below. | |
281 | |
282 Typical user cache directories are: | |
283 Mac OS X: ~/Library/Caches/<AppName> | |
284 Unix: ~/.cache/<AppName> (XDG default) | |
285 Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache | |
286 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache | |
287 | |
288 On Windows the only suggestion in the MSDN docs is that local settings go in | |
289 the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming | |
290 app data dir (the default returned by `user_data_dir` above). Apps typically | |
291 put cache data somewhere *under* the given dir here. Some examples: | |
292 ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache | |
293 ...\Acme\SuperApp\Cache\1.0 | |
294 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. | |
295 This can be disabled with the `opinion=False` option. | |
296 """ | |
297 if system == "win32": | |
298 if appauthor is None: | |
299 appauthor = appname | |
300 path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) | |
301 # When using Python 2, return paths as bytes on Windows like we do on | |
302 # other operating systems. See helper function docs for more details. | |
303 if not PY3 and isinstance(path, unicode): | |
304 path = _win_path_to_bytes(path) | |
305 if appname: | |
306 if appauthor is not False: | |
307 path = os.path.join(path, appauthor, appname) | |
308 else: | |
309 path = os.path.join(path, appname) | |
310 if opinion: | |
311 path = os.path.join(path, "Cache") | |
312 elif system == 'darwin': | |
313 path = os.path.expanduser('~/Library/Caches') | |
314 if appname: | |
315 path = os.path.join(path, appname) | |
316 else: | |
317 path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) | |
318 if appname: | |
319 path = os.path.join(path, appname) | |
320 if appname and version: | |
321 path = os.path.join(path, version) | |
322 return path | |
323 | |
324 | |
325 def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): | |
326 r"""Return full path to the user-specific state dir for this application. | |
327 | |
328 "appname" is the name of application. | |
329 If None, just the system directory is returned. | |
330 "appauthor" (only used on Windows) is the name of the | |
331 appauthor or distributing body for this application. Typically | |
332 it is the owning company name. This falls back to appname. You may | |
333 pass False to disable it. | |
334 "version" is an optional version path element to append to the | |
335 path. You might want to use this if you want multiple versions | |
336 of your app to be able to run independently. If used, this | |
337 would typically be "<major>.<minor>". | |
338 Only applied when appname is present. | |
339 "roaming" (boolean, default False) can be set True to use the Windows | |
340 roaming appdata directory. That means that for users on a Windows | |
341 network setup for roaming profiles, this user data will be | |
342 sync'd on login. See | |
343 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> | |
344 for a discussion of issues. | |
345 | |
346 Typical user state directories are: | |
347 Mac OS X: same as user_data_dir | |
348 Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined | |
349 Win *: same as user_data_dir | |
350 | |
351 For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> | |
352 to extend the XDG spec and support $XDG_STATE_HOME. | |
353 | |
354 That means, by default "~/.local/state/<AppName>". | |
355 """ | |
356 if system in ["win32", "darwin"]: | |
357 path = user_data_dir(appname, appauthor, None, roaming) | |
358 else: | |
359 path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) | |
360 if appname: | |
361 path = os.path.join(path, appname) | |
362 if appname and version: | |
363 path = os.path.join(path, version) | |
364 return path | |
365 | |
366 | |
367 def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): | |
368 r"""Return full path to the user-specific log dir for this application. | |
369 | |
370 "appname" is the name of application. | |
371 If None, just the system directory is returned. | |
372 "appauthor" (only used on Windows) is the name of the | |
373 appauthor or distributing body for this application. Typically | |
374 it is the owning company name. This falls back to appname. You may | |
375 pass False to disable it. | |
376 "version" is an optional version path element to append to the | |
377 path. You might want to use this if you want multiple versions | |
378 of your app to be able to run independently. If used, this | |
379 would typically be "<major>.<minor>". | |
380 Only applied when appname is present. | |
381 "opinion" (boolean) can be False to disable the appending of | |
382 "Logs" to the base app data dir for Windows, and "log" to the | |
383 base cache dir for Unix. See discussion below. | |
384 | |
385 Typical user log directories are: | |
386 Mac OS X: ~/Library/Logs/<AppName> | |
387 Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined | |
388 Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs | |
389 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs | |
390 | |
391 On Windows the only suggestion in the MSDN docs is that local settings | |
392 go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in | |
393 examples of what some windows apps use for a logs dir.) | |
394 | |
395 OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` | |
396 value for Windows and appends "log" to the user cache dir for Unix. | |
397 This can be disabled with the `opinion=False` option. | |
398 """ | |
399 if system == "darwin": | |
400 path = os.path.join( | |
401 os.path.expanduser('~/Library/Logs'), | |
402 appname) | |
403 elif system == "win32": | |
404 path = user_data_dir(appname, appauthor, version) | |
405 version = False | |
406 if opinion: | |
407 path = os.path.join(path, "Logs") | |
408 else: | |
409 path = user_cache_dir(appname, appauthor, version) | |
410 version = False | |
411 if opinion: | |
412 path = os.path.join(path, "log") | |
413 if appname and version: | |
414 path = os.path.join(path, version) | |
415 return path | |
416 | |
417 | |
418 class AppDirs(object): | |
419 """Convenience wrapper for getting application dirs.""" | |
420 def __init__(self, appname=None, appauthor=None, version=None, | |
421 roaming=False, multipath=False): | |
422 self.appname = appname | |
423 self.appauthor = appauthor | |
424 self.version = version | |
425 self.roaming = roaming | |
426 self.multipath = multipath | |
427 | |
428 @property | |
429 def user_data_dir(self): | |
430 return user_data_dir(self.appname, self.appauthor, | |
431 version=self.version, roaming=self.roaming) | |
432 | |
433 @property | |
434 def site_data_dir(self): | |
435 return site_data_dir(self.appname, self.appauthor, | |
436 version=self.version, multipath=self.multipath) | |
437 | |
438 @property | |
439 def user_config_dir(self): | |
440 return user_config_dir(self.appname, self.appauthor, | |
441 version=self.version, roaming=self.roaming) | |
442 | |
443 @property | |
444 def site_config_dir(self): | |
445 return site_config_dir(self.appname, self.appauthor, | |
446 version=self.version, multipath=self.multipath) | |
447 | |
448 @property | |
449 def user_cache_dir(self): | |
450 return user_cache_dir(self.appname, self.appauthor, | |
451 version=self.version) | |
452 | |
453 @property | |
454 def user_state_dir(self): | |
455 return user_state_dir(self.appname, self.appauthor, | |
456 version=self.version) | |
457 | |
458 @property | |
459 def user_log_dir(self): | |
460 return user_log_dir(self.appname, self.appauthor, | |
461 version=self.version) | |
462 | |
463 | |
464 #---- internal support stuff | |
465 | |
466 def _get_win_folder_from_registry(csidl_name): | |
467 """This is a fallback technique at best. I'm not sure if using the | |
468 registry for this guarantees us the correct answer for all CSIDL_* | |
469 names. | |
470 """ | |
471 if PY3: | |
472 import winreg as _winreg | |
473 else: | |
474 import _winreg | |
475 | |
476 shell_folder_name = { | |
477 "CSIDL_APPDATA": "AppData", | |
478 "CSIDL_COMMON_APPDATA": "Common AppData", | |
479 "CSIDL_LOCAL_APPDATA": "Local AppData", | |
480 }[csidl_name] | |
481 | |
482 key = _winreg.OpenKey( | |
483 _winreg.HKEY_CURRENT_USER, | |
484 r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" | |
485 ) | |
486 dir, type = _winreg.QueryValueEx(key, shell_folder_name) | |
487 return dir | |
488 | |
489 | |
490 def _get_win_folder_with_pywin32(csidl_name): | |
491 from win32com.shell import shellcon, shell | |
492 dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) | |
493 # Try to make this a unicode path because SHGetFolderPath does | |
494 # not return unicode strings when there is unicode data in the | |
495 # path. | |
496 try: | |
497 dir = unicode(dir) | |
498 | |
499 # Downgrade to short path name if have highbit chars. See | |
500 # <http://bugs.activestate.com/show_bug.cgi?id=85099>. | |
501 has_high_char = False | |
502 for c in dir: | |
503 if ord(c) > 255: | |
504 has_high_char = True | |
505 break | |
506 if has_high_char: | |
507 try: | |
508 import win32api | |
509 dir = win32api.GetShortPathName(dir) | |
510 except ImportError: | |
511 pass | |
512 except UnicodeError: | |
513 pass | |
514 return dir | |
515 | |
516 | |
517 def _get_win_folder_with_ctypes(csidl_name): | |
518 import ctypes | |
519 | |
520 csidl_const = { | |
521 "CSIDL_APPDATA": 26, | |
522 "CSIDL_COMMON_APPDATA": 35, | |
523 "CSIDL_LOCAL_APPDATA": 28, | |
524 }[csidl_name] | |
525 | |
526 buf = ctypes.create_unicode_buffer(1024) | |
527 ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) | |
528 | |
529 # Downgrade to short path name if have highbit chars. See | |
530 # <http://bugs.activestate.com/show_bug.cgi?id=85099>. | |
531 has_high_char = False | |
532 for c in buf: | |
533 if ord(c) > 255: | |
534 has_high_char = True | |
535 break | |
536 if has_high_char: | |
537 buf2 = ctypes.create_unicode_buffer(1024) | |
538 if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): | |
539 buf = buf2 | |
540 | |
541 return buf.value | |
542 | |
543 def _get_win_folder_with_jna(csidl_name): | |
544 import array | |
545 from com.sun import jna | |
546 from com.sun.jna.platform import win32 | |
547 | |
548 buf_size = win32.WinDef.MAX_PATH * 2 | |
549 buf = array.zeros('c', buf_size) | |
550 shell = win32.Shell32.INSTANCE | |
551 shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) | |
552 dir = jna.Native.toString(buf.tostring()).rstrip("\0") | |
553 | |
554 # Downgrade to short path name if have highbit chars. See | |
555 # <http://bugs.activestate.com/show_bug.cgi?id=85099>. | |
556 has_high_char = False | |
557 for c in dir: | |
558 if ord(c) > 255: | |
559 has_high_char = True | |
560 break | |
561 if has_high_char: | |
562 buf = array.zeros('c', buf_size) | |
563 kernel = win32.Kernel32.INSTANCE | |
564 if kernel.GetShortPathName(dir, buf, buf_size): | |
565 dir = jna.Native.toString(buf.tostring()).rstrip("\0") | |
566 | |
567 return dir | |
568 | |
569 if system == "win32": | |
570 try: | |
571 from ctypes import windll | |
572 _get_win_folder = _get_win_folder_with_ctypes | |
573 except ImportError: | |
574 try: | |
575 import com.sun.jna | |
576 _get_win_folder = _get_win_folder_with_jna | |
577 except ImportError: | |
578 _get_win_folder = _get_win_folder_from_registry | |
579 | |
580 | |
581 def _win_path_to_bytes(path): | |
582 """Encode Windows paths to bytes. Only used on Python 2. | |
583 | |
584 Motivation is to be consistent with other operating systems where paths | |
585 are also returned as bytes. This avoids problems mixing bytes and Unicode | |
586 elsewhere in the codebase. For more details and discussion see | |
587 <https://github.com/pypa/pip/issues/3463>. | |
588 | |
589 If encoding using ASCII and MBCS fails, return the original Unicode path. | |
590 """ | |
591 for encoding in ('ASCII', 'MBCS'): | |
592 try: | |
593 return path.encode(encoding) | |
594 except (UnicodeEncodeError, LookupError): | |
595 pass | |
596 return path | |
597 | |
598 | |
599 #---- self test code | |
600 | |
601 if __name__ == "__main__": | |
602 appname = "MyApp" | |
603 appauthor = "MyCompany" | |
604 | |
605 props = ("user_data_dir", | |
606 "user_config_dir", | |
607 "user_cache_dir", | |
608 "user_state_dir", | |
609 "user_log_dir", | |
610 "site_data_dir", | |
611 "site_config_dir") | |
612 | |
613 print("-- app dirs %s --" % __version__) | |
614 | |
615 print("-- app dirs (with optional 'version')") | |
616 dirs = AppDirs(appname, appauthor, version="1.0") | |
617 for prop in props: | |
618 print("%s: %s" % (prop, getattr(dirs, prop))) | |
619 | |
620 print("\n-- app dirs (without optional 'version')") | |
621 dirs = AppDirs(appname, appauthor) | |
622 for prop in props: | |
623 print("%s: %s" % (prop, getattr(dirs, prop))) | |
624 | |
625 print("\n-- app dirs (without optional 'appauthor')") | |
626 dirs = AppDirs(appname) | |
627 for prop in props: | |
628 print("%s: %s" % (prop, getattr(dirs, prop))) | |
629 | |
630 print("\n-- app dirs (with disabled 'appauthor')") | |
631 dirs = AppDirs(appname, appauthor=False) | |
632 for prop in props: | |
633 print("%s: %s" % (prop, getattr(dirs, prop))) |