Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Side by Side Diff: third_party/google-endpoints/appdirs.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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#XSLTH31941211 23120121120120
13 # - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileS ystem/index.html
14 # - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spe c-latest.html
15
16 __version_info__ = (1, 4, 0)
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 else:
41 system = sys.platform
42
43
44
45 def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
46 r"""Return full path to the user-specific data dir for this application.
47
48 "appname" is the name of application.
49 If None, just the system directory is returned.
50 "appauthor" (only used on Windows) is the name of the
51 appauthor or distributing body for this application. Typically
52 it is the owning company name. This falls back to appname. You may
53 pass False to disable it.
54 "version" is an optional version path element to append to the
55 path. You might want to use this if you want multiple versions
56 of your app to be able to run independently. If used, this
57 would typically be "<major>.<minor>".
58 Only applied when appname is present.
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
66 Typical user data directories are:
67 Mac OS X: ~/Library/Application Support/<AppName>
68 Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HO ME, if defined
69 Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
70 Win XP (roaming): C:\Documents and Settings\<username>\Local Setti ngs\Application Data\<AppAuthor>\<AppName>
71 Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<A ppName>
72 Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\ <AppName>
73
74 For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
75 That means, by default "~/.local/share/<AppName>".
76 """
77 if system == "win32":
78 if appauthor is None:
79 appauthor = appname
80 const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
81 path = os.path.normpath(_get_win_folder(const))
82 if appname:
83 if appauthor is not False:
84 path = os.path.join(path, appauthor, appname)
85 else:
86 path = os.path.join(path, appname)
87 elif system == 'darwin':
88 path = os.path.expanduser('~/Library/Application Support/')
89 if appname:
90 path = os.path.join(path, appname)
91 else:
92 path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
93 if appname:
94 path = os.path.join(path, appname)
95 if appname and version:
96 path = os.path.join(path, version)
97 return path
98
99
100 def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
101 """Return full path to the user-shared data dir for this application.
102
103 "appname" is the name of application.
104 If None, just the system directory is returned.
105 "appauthor" (only used on Windows) is the name of the
106 appauthor or distributing body for this application. Typically
107 it is the owning company name. This falls back to appname. You may
108 pass False to disable it.
109 "version" is an optional version path element to append to the
110 path. You might want to use this if you want multiple versions
111 of your app to be able to run independently. If used, this
112 would typically be "<major>.<minor>".
113 Only applied when appname is present.
114 "multipath" is an optional parameter only applicable to *nix
115 which indicates that the entire list of data dirs should be
116 returned. By default, the first item from XDG_DATA_DIRS is
117 returned, or '/usr/local/share/<AppName>',
118 if XDG_DATA_DIRS is not set
119
120 Typical user data directories are:
121 Mac OS X: /Library/Application Support/<AppName>
122 Unix: /usr/local/share/<AppName> or /usr/share/<AppName>
123 Win XP: C:\Documents and Settings\All Users\Application Data\<AppAut hor>\<AppName>
124 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vi sta.)
125 Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeab le on Win 7.
126
127 For Unix, this is using the $XDG_DATA_DIRS[0] default.
128
129 WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
130 """
131 if system == "win32":
132 if appauthor is None:
133 appauthor = appname
134 path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
135 if appname:
136 if appauthor is not False:
137 path = os.path.join(path, appauthor, appname)
138 else:
139 path = os.path.join(path, appname)
140 elif system == 'darwin':
141 path = os.path.expanduser('/Library/Application Support')
142 if appname:
143 path = os.path.join(path, appname)
144 else:
145 # XDG default for $XDG_DATA_DIRS
146 # only first, if multipath is False
147 path = os.getenv('XDG_DATA_DIRS',
148 os.pathsep.join(['/usr/local/share', '/usr/share']))
149 pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os. pathsep)]
150 if appname:
151 if version:
152 appname = os.path.join(appname, version)
153 pathlist = [os.sep.join([x, appname]) for x in pathlist]
154
155 if multipath:
156 path = os.pathsep.join(pathlist)
157 else:
158 path = pathlist[0]
159 return path
160
161 if appname and version:
162 path = os.path.join(path, version)
163 return path
164
165
166 def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
167 r"""Return full path to the user-specific config dir for this application.
168
169 "appname" is the name of application.
170 If None, just the system directory is returned.
171 "appauthor" (only used on Windows) is the name of the
172 appauthor or distributing body for this application. Typically
173 it is the owning company name. This falls back to appname. You may
174 pass False to disable it.
175 "version" is an optional version path element to append to the
176 path. You might want to use this if you want multiple versions
177 of your app to be able to run independently. If used, this
178 would typically be "<major>.<minor>".
179 Only applied when appname is present.
180 "roaming" (boolean, default False) can be set True to use the Windows
181 roaming appdata directory. That means that for users on a Windows
182 network setup for roaming profiles, this user data will be
183 sync'd on login. See
184 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
185 for a discussion of issues.
186
187 Typical user data directories are:
188 Mac OS X: same as user_data_dir
189 Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME , if defined
190 Win *: same as user_data_dir
191
192 For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
193 That means, by deafult "~/.config/<AppName>".
194 """
195 if system in ["win32", "darwin"]:
196 path = user_data_dir(appname, appauthor, None, roaming)
197 else:
198 path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
199 if appname:
200 path = os.path.join(path, appname)
201 if appname and version:
202 path = os.path.join(path, version)
203 return path
204
205
206 def site_config_dir(appname=None, appauthor=None, version=None, multipath=False) :
207 """Return full path to the user-shared data dir for this application.
208
209 "appname" is the name of application.
210 If None, just the system directory is returned.
211 "appauthor" (only used on Windows) is the name of the
212 appauthor or distributing body for this application. Typically
213 it is the owning company name. This falls back to appname. You may
214 pass False to disable it.
215 "version" is an optional version path element to append to the
216 path. You might want to use this if you want multiple versions
217 of your app to be able to run independently. If used, this
218 would typically be "<major>.<minor>".
219 Only applied when appname is present.
220 "multipath" is an optional parameter only applicable to *nix
221 which indicates that the entire list of config dirs should be
222 returned. By default, the first item from XDG_CONFIG_DIRS is
223 returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set
224
225 Typical user data directories are:
226 Mac OS X: same as site_data_dir
227 Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in
228 $XDG_CONFIG_DIRS
229 Win *: same as site_data_dir
230 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vi sta.)
231
232 For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False
233
234 WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
235 """
236 if system in ["win32", "darwin"]:
237 path = site_data_dir(appname, appauthor)
238 if appname and version:
239 path = os.path.join(path, version)
240 else:
241 # XDG default for $XDG_CONFIG_DIRS
242 # only first, if multipath is False
243 path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
244 pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os. pathsep)]
245 if appname:
246 if version:
247 appname = os.path.join(appname, version)
248 pathlist = [os.sep.join([x, appname]) for x in pathlist]
249
250 if multipath:
251 path = os.pathsep.join(pathlist)
252 else:
253 path = pathlist[0]
254 return path
255
256
257 def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
258 r"""Return full path to the user-specific cache dir for this application.
259
260 "appname" is the name of application.
261 If None, just the system directory is returned.
262 "appauthor" (only used on Windows) is the name of the
263 appauthor or distributing body for this application. Typically
264 it is the owning company name. This falls back to appname. You may
265 pass False to disable it.
266 "version" is an optional version path element to append to the
267 path. You might want to use this if you want multiple versions
268 of your app to be able to run independently. If used, this
269 would typically be "<major>.<minor>".
270 Only applied when appname is present.
271 "opinion" (boolean) can be False to disable the appending of
272 "Cache" to the base app data dir for Windows. See
273 discussion below.
274
275 Typical user cache directories are:
276 Mac OS X: ~/Library/Caches/<AppName>
277 Unix: ~/.cache/<AppName> (XDG default)
278 Win XP: C:\Documents and Settings\<username>\Local Settings\Applicat ion Data\<AppAuthor>\<AppName>\Cache
279 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cach e
280
281 On Windows the only suggestion in the MSDN docs is that local settings go in
282 the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming
283 app data dir (the default returned by `user_data_dir` above). Apps typically
284 put cache data somewhere *under* the given dir here. Some examples:
285 ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
286 ...\Acme\SuperApp\Cache\1.0
287 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
288 This can be disabled with the `opinion=False` option.
289 """
290 if system == "win32":
291 if appauthor is None:
292 appauthor = appname
293 path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
294 if appname:
295 if appauthor is not False:
296 path = os.path.join(path, appauthor, appname)
297 else:
298 path = os.path.join(path, appname)
299 if opinion:
300 path = os.path.join(path, "Cache")
301 elif system == 'darwin':
302 path = os.path.expanduser('~/Library/Caches')
303 if appname:
304 path = os.path.join(path, appname)
305 else:
306 path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
307 if appname:
308 path = os.path.join(path, appname)
309 if appname and version:
310 path = os.path.join(path, version)
311 return path
312
313
314 def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
315 r"""Return full path to the user-specific log dir for this application.
316
317 "appname" is the name of application.
318 If None, just the system directory is returned.
319 "appauthor" (only used on Windows) is the name of the
320 appauthor or distributing body for this application. Typically
321 it is the owning company name. This falls back to appname. You may
322 pass False to disable it.
323 "version" is an optional version path element to append to the
324 path. You might want to use this if you want multiple versions
325 of your app to be able to run independently. If used, this
326 would typically be "<major>.<minor>".
327 Only applied when appname is present.
328 "opinion" (boolean) can be False to disable the appending of
329 "Logs" to the base app data dir for Windows, and "log" to the
330 base cache dir for Unix. See discussion below.
331
332 Typical user cache directories are:
333 Mac OS X: ~/Library/Logs/<AppName>
334 Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if define d
335 Win XP: C:\Documents and Settings\<username>\Local Settings\Applicat ion Data\<AppAuthor>\<AppName>\Logs
336 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs
337
338 On Windows the only suggestion in the MSDN docs is that local settings
339 go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in
340 examples of what some windows apps use for a logs dir.)
341
342 OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA`
343 value for Windows and appends "log" to the user cache dir for Unix.
344 This can be disabled with the `opinion=False` option.
345 """
346 if system == "darwin":
347 path = os.path.join(
348 os.path.expanduser('~/Library/Logs'),
349 appname)
350 elif system == "win32":
351 path = user_data_dir(appname, appauthor, version)
352 version = False
353 if opinion:
354 path = os.path.join(path, "Logs")
355 else:
356 path = user_cache_dir(appname, appauthor, version)
357 version = False
358 if opinion:
359 path = os.path.join(path, "log")
360 if appname and version:
361 path = os.path.join(path, version)
362 return path
363
364
365 class AppDirs(object):
366 """Convenience wrapper for getting application dirs."""
367 def __init__(self, appname, appauthor=None, version=None, roaming=False,
368 multipath=False):
369 self.appname = appname
370 self.appauthor = appauthor
371 self.version = version
372 self.roaming = roaming
373 self.multipath = multipath
374
375 @property
376 def user_data_dir(self):
377 return user_data_dir(self.appname, self.appauthor,
378 version=self.version, roaming=self.roaming)
379
380 @property
381 def site_data_dir(self):
382 return site_data_dir(self.appname, self.appauthor,
383 version=self.version, multipath=self.multipath)
384
385 @property
386 def user_config_dir(self):
387 return user_config_dir(self.appname, self.appauthor,
388 version=self.version, roaming=self.roaming)
389
390 @property
391 def site_config_dir(self):
392 return site_config_dir(self.appname, self.appauthor,
393 version=self.version, multipath=self.multipath)
394
395 @property
396 def user_cache_dir(self):
397 return user_cache_dir(self.appname, self.appauthor,
398 version=self.version)
399
400 @property
401 def user_log_dir(self):
402 return user_log_dir(self.appname, self.appauthor,
403 version=self.version)
404
405
406 #---- internal support stuff
407
408 def _get_win_folder_from_registry(csidl_name):
409 """This is a fallback technique at best. I'm not sure if using the
410 registry for this guarantees us the correct answer for all CSIDL_*
411 names.
412 """
413 import _winreg
414
415 shell_folder_name = {
416 "CSIDL_APPDATA": "AppData",
417 "CSIDL_COMMON_APPDATA": "Common AppData",
418 "CSIDL_LOCAL_APPDATA": "Local AppData",
419 }[csidl_name]
420
421 key = _winreg.OpenKey(
422 _winreg.HKEY_CURRENT_USER,
423 r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
424 )
425 dir, type = _winreg.QueryValueEx(key, shell_folder_name)
426 return dir
427
428
429 def _get_win_folder_with_pywin32(csidl_name):
430 from win32com.shell import shellcon, shell
431 dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
432 # Try to make this a unicode path because SHGetFolderPath does
433 # not return unicode strings when there is unicode data in the
434 # path.
435 try:
436 dir = unicode(dir)
437
438 # Downgrade to short path name if have highbit chars. See
439 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
440 has_high_char = False
441 for c in dir:
442 if ord(c) > 255:
443 has_high_char = True
444 break
445 if has_high_char:
446 try:
447 import win32api
448 dir = win32api.GetShortPathName(dir)
449 except ImportError:
450 pass
451 except UnicodeError:
452 pass
453 return dir
454
455
456 def _get_win_folder_with_ctypes(csidl_name):
457 import ctypes
458
459 csidl_const = {
460 "CSIDL_APPDATA": 26,
461 "CSIDL_COMMON_APPDATA": 35,
462 "CSIDL_LOCAL_APPDATA": 28,
463 }[csidl_name]
464
465 buf = ctypes.create_unicode_buffer(1024)
466 ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
467
468 # Downgrade to short path name if have highbit chars. See
469 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
470 has_high_char = False
471 for c in buf:
472 if ord(c) > 255:
473 has_high_char = True
474 break
475 if has_high_char:
476 buf2 = ctypes.create_unicode_buffer(1024)
477 if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
478 buf = buf2
479
480 return buf.value
481
482 def _get_win_folder_with_jna(csidl_name):
483 import array
484 from com.sun import jna
485 from com.sun.jna.platform import win32
486
487 buf_size = win32.WinDef.MAX_PATH * 2
488 buf = array.zeros('c', buf_size)
489 shell = win32.Shell32.INSTANCE
490 shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.S hlObj.SHGFP_TYPE_CURRENT, buf)
491 dir = jna.Native.toString(buf.tostring()).rstrip("\0")
492
493 # Downgrade to short path name if have highbit chars. See
494 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
495 has_high_char = False
496 for c in dir:
497 if ord(c) > 255:
498 has_high_char = True
499 break
500 if has_high_char:
501 buf = array.zeros('c', buf_size)
502 kernel = win32.Kernel32.INSTANCE
503 if kernal.GetShortPathName(dir, buf, buf_size):
504 dir = jna.Native.toString(buf.tostring()).rstrip("\0")
505
506 return dir
507
508 if system == "win32":
509 try:
510 import win32com.shell
511 _get_win_folder = _get_win_folder_with_pywin32
512 except ImportError:
513 try:
514 from ctypes import windll
515 _get_win_folder = _get_win_folder_with_ctypes
516 except ImportError:
517 try:
518 import com.sun.jna
519 _get_win_folder = _get_win_folder_with_jna
520 except ImportError:
521 _get_win_folder = _get_win_folder_from_registry
522
523
524 #---- self test code
525
526 if __name__ == "__main__":
527 appname = "MyApp"
528 appauthor = "MyCompany"
529
530 props = ("user_data_dir", "site_data_dir",
531 "user_config_dir", "site_config_dir",
532 "user_cache_dir", "user_log_dir")
533
534 print("-- app dirs (with optional 'version')")
535 dirs = AppDirs(appname, appauthor, version="1.0")
536 for prop in props:
537 print("%s: %s" % (prop, getattr(dirs, prop)))
538
539 print("\n-- app dirs (without optional 'version')")
540 dirs = AppDirs(appname, appauthor)
541 for prop in props:
542 print("%s: %s" % (prop, getattr(dirs, prop)))
543
544 print("\n-- app dirs (without optional 'appauthor')")
545 dirs = AppDirs(appname)
546 for prop in props:
547 print("%s: %s" % (prop, getattr(dirs, prop)))
548
549 print("\n-- app dirs (with disabled 'appauthor')")
550 dirs = AppDirs(appname, appauthor=False)
551 for prop in props:
552 print("%s: %s" % (prop, getattr(dirs, prop)))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698