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)))