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