2 # -*- coding: utf-8 -*-
3 # Copyright (c) 2005-2010 ActiveState Software Inc.
4 # Copyright (c) 2013 Eddy Petrișor
6 """Utilities for determining application-specific dirs.
8 See <http://github.com/ActiveState/appdirs> for details and usage.
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
16 __version_info__ = (1, 3, 0)
17 __version__ = '.'.join(map(str, __version_info__))
23 PY3 = sys.version_info[0] == 3
30 def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
31 r"""Return full path to the user-specific data dir for this application.
33 "appname" is the name of application.
34 If None, just the system directory is returned.
35 "appauthor" (only required and used on Windows) is the name of the
36 appauthor or distributing body for this application. Typically
37 it is the owning company name. This falls back to appname.
38 "version" is an optional version path element to append to the
39 path. You might want to use this if you want multiple versions
40 of your app to be able to run independently. If used, this
41 would typically be "<major>.<minor>".
42 Only applied when appname is present.
43 "roaming" (boolean, default False) can be set True to use the Windows
44 roaming appdata directory. That means that for users on a Windows
45 network setup for roaming profiles, this user data will be
47 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
48 for a discussion of issues.
50 Typical user data directories are:
51 Mac OS X: ~/Library/Application Support/<AppName>
52 Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined
53 Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
54 Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>
55 Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>
56 Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName>
58 For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
59 That means, by deafult "~/.local/share/<AppName>".
61 if sys.platform == "win32":
64 const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
65 path = os.path.normpath(_get_win_folder(const))
67 path = os.path.join(path, appauthor, appname)
68 elif sys.platform == 'darwin':
69 path = os.path.expanduser('~/Library/Application Support/')
71 path = os.path.join(path, appname)
73 path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
75 path = os.path.join(path, appname)
76 if appname and version:
77 path = os.path.join(path, version)
81 def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
82 """Return full path to the user-shared data dir for this application.
84 "appname" is the name of application.
85 If None, just the system directory is returned.
86 "appauthor" (only required and used on Windows) is the name of the
87 appauthor or distributing body for this application. Typically
88 it is the owning company name. This falls back to appname.
89 "version" is an optional version path element to append to the
90 path. You might want to use this if you want multiple versions
91 of your app to be able to run independently. If used, this
92 would typically be "<major>.<minor>".
93 Only applied when appname is present.
94 "multipath" is an optional parameter only applicable to *nix
95 which indicates that the entire list of data dirs should be
96 returned. By default, the first item from XDG_DATA_DIRS is
97 returned, or '/usr/local/share/<AppName>',
98 if XDG_DATA_DIRS is not set
100 Typical user data directories are:
101 Mac OS X: /Library/Application Support/<AppName>
102 Unix: /usr/local/share/<AppName> or /usr/share/<AppName>
103 Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName>
104 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
105 Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7.
107 For Unix, this is using the $XDG_DATA_DIRS[0] default.
109 WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
111 if sys.platform == "win32":
112 if appauthor is None:
114 path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
116 path = os.path.join(path, appauthor, appname)
117 elif sys.platform == 'darwin':
118 path = os.path.expanduser('/Library/Application Support')
120 path = os.path.join(path, appname)
122 # XDG default for $XDG_DATA_DIRS
123 # only first, if multipath is False
124 path = os.getenv('XDG_DATA_DIRS',
125 os.pathsep.join(['/usr/local/share', '/usr/share']))
126 pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
129 appname = os.path.join(appname, version)
130 pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
133 path = os.pathsep.join(pathlist)
138 if appname and version:
139 path = os.path.join(path, version)
143 def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
144 r"""Return full path to the user-specific config dir for this application.
146 "appname" is the name of application.
147 If None, just the system directory is returned.
148 "appauthor" (only required and used on Windows) is the name of the
149 appauthor or distributing body for this application. Typically
150 it is the owning company name. This falls back to appname.
151 "version" is an optional version path element to append to the
152 path. You might want to use this if you want multiple versions
153 of your app to be able to run independently. If used, this
154 would typically be "<major>.<minor>".
155 Only applied when appname is present.
156 "roaming" (boolean, default False) can be set True to use the Windows
157 roaming appdata directory. That means that for users on a Windows
158 network setup for roaming profiles, this user data will be
160 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
161 for a discussion of issues.
163 Typical user data directories are:
164 Mac OS X: same as user_data_dir
165 Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined
166 Win *: same as user_data_dir
168 For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
169 That means, by deafult "~/.local/share/<AppName>".
171 if sys.platform in [ "win32", "darwin" ]:
172 path = user_data_dir(appname, appauthor, None, roaming)
174 path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
176 path = os.path.join(path, appname)
177 if appname and version:
178 path = os.path.join(path, version)
182 def site_config_dir(appname=None, appauthor=None, version=None, multipath=False):
183 """Return full path to the user-shared data dir for this application.
185 "appname" is the name of application.
186 If None, just the system directory is returned.
187 "appauthor" (only required and used on Windows) is the name of the
188 appauthor or distributing body for this application. Typically
189 it is the owning company name. This falls back to appname.
190 "version" is an optional version path element to append to the
191 path. You might want to use this if you want multiple versions
192 of your app to be able to run independently. If used, this
193 would typically be "<major>.<minor>".
194 Only applied when appname is present.
195 "multipath" is an optional parameter only applicable to *nix
196 which indicates that the entire list of config dirs should be
197 returned. By default, the first item from XDG_CONFIG_DIRS is
198 returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set
200 Typical user data directories are:
201 Mac OS X: same as site_data_dir
202 Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in
204 Win *: same as site_data_dir
205 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
207 For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False
209 WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
211 if sys.platform in [ "win32", "darwin" ]:
212 path = site_data_dir(appname, appauthor)
213 if appname and version:
214 path = os.path.join(path, version)
216 # XDG default for $XDG_CONFIG_DIRS
217 # only first, if multipath is False
218 path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
219 pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
222 appname = os.path.join(appname, version)
223 pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
226 path = os.pathsep.join(pathlist)
231 def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
232 r"""Return full path to the user-specific cache dir for this application.
234 "appname" is the name of application.
235 If None, just the system directory is returned.
236 "appauthor" (only required and used on Windows) is the name of the
237 appauthor or distributing body for this application. Typically
238 it is the owning company name. This falls back to appname.
239 "version" is an optional version path element to append to the
240 path. You might want to use this if you want multiple versions
241 of your app to be able to run independently. If used, this
242 would typically be "<major>.<minor>".
243 Only applied when appname is present.
244 "opinion" (boolean) can be False to disable the appending of
245 "Cache" to the base app data dir for Windows. See
248 Typical user cache directories are:
249 Mac OS X: ~/Library/Caches/<AppName>
250 Unix: ~/.cache/<AppName> (XDG default)
251 Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache
252 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache
254 On Windows the only suggestion in the MSDN docs is that local settings go in
255 the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming
256 app data dir (the default returned by `user_data_dir` above). Apps typically
257 put cache data somewhere *under* the given dir here. Some examples:
258 ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
259 ...\Acme\SuperApp\Cache\1.0
260 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
261 This can be disabled with the `opinion=False` option.
263 if sys.platform == "win32":
264 if appauthor is None:
266 path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
268 path = os.path.join(path, appauthor, appname)
270 path = os.path.join(path, "Cache")
271 elif sys.platform == 'darwin':
272 path = os.path.expanduser('~/Library/Caches')
274 path = os.path.join(path, appname)
276 path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
278 path = os.path.join(path, appname)
279 if appname and version:
280 path = os.path.join(path, version)
283 def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
284 r"""Return full path to the user-specific log dir for this application.
286 "appname" is the name of application.
287 If None, just the system directory is returned.
288 "appauthor" (only required and used on Windows) is the name of the
289 appauthor or distributing body for this application. Typically
290 it is the owning company name. This falls back to appname.
291 "version" is an optional version path element to append to the
292 path. You might want to use this if you want multiple versions
293 of your app to be able to run independently. If used, this
294 would typically be "<major>.<minor>".
295 Only applied when appname is present.
296 "opinion" (boolean) can be False to disable the appending of
297 "Logs" to the base app data dir for Windows, and "log" to the
298 base cache dir for Unix. See discussion below.
300 Typical user cache directories are:
301 Mac OS X: ~/Library/Logs/<AppName>
302 Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined
303 Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs
304 Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs
306 On Windows the only suggestion in the MSDN docs is that local settings
307 go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in
308 examples of what some windows apps use for a logs dir.)
310 OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA`
311 value for Windows and appends "log" to the user cache dir for Unix.
312 This can be disabled with the `opinion=False` option.
314 if sys.platform == "darwin":
316 os.path.expanduser('~/Library/Logs'),
318 elif sys.platform == "win32":
319 path = user_data_dir(appname, appauthor, version); version=False
321 path = os.path.join(path, "Logs")
323 path = user_cache_dir(appname, appauthor, version); version=False
325 path = os.path.join(path, "log")
326 if appname and version:
327 path = os.path.join(path, version)
331 class AppDirs(object):
332 """Convenience wrapper for getting application dirs."""
333 def __init__(self, appname, appauthor=None, version=None,
334 roaming=False, multipath=False):
335 self.appname = appname
336 self.appauthor = appauthor
337 self.version = version
338 self.roaming = roaming
339 self.multipath = multipath
341 def user_data_dir(self):
342 return user_data_dir(self.appname, self.appauthor,
343 version=self.version, roaming=self.roaming)
345 def site_data_dir(self):
346 return site_data_dir(self.appname, self.appauthor,
347 version=self.version, multipath=self.multipath)
349 def user_config_dir(self):
350 return user_config_dir(self.appname, self.appauthor,
351 version=self.version, roaming=self.roaming)
353 def site_config_dir(self):
354 return site_data_dir(self.appname, self.appauthor,
355 version=self.version, multipath=self.multipath)
357 def user_cache_dir(self):
358 return user_cache_dir(self.appname, self.appauthor,
359 version=self.version)
361 def user_log_dir(self):
362 return user_log_dir(self.appname, self.appauthor,
363 version=self.version)
368 #---- internal support stuff
370 def _get_win_folder_from_registry(csidl_name):
371 """This is a fallback technique at best. I'm not sure if using the
372 registry for this guarantees us the correct answer for all CSIDL_*
377 shell_folder_name = {
378 "CSIDL_APPDATA": "AppData",
379 "CSIDL_COMMON_APPDATA": "Common AppData",
380 "CSIDL_LOCAL_APPDATA": "Local AppData",
383 key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
384 r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
385 dir, type = _winreg.QueryValueEx(key, shell_folder_name)
388 def _get_win_folder_with_pywin32(csidl_name):
389 from win32com.shell import shellcon, shell
390 dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
391 # Try to make this a unicode path because SHGetFolderPath does
392 # not return unicode strings when there is unicode data in the
397 # Downgrade to short path name if have highbit chars. See
398 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
399 has_high_char = False
407 dir = win32api.GetShortPathName(dir)
414 def _get_win_folder_with_ctypes(csidl_name):
419 "CSIDL_COMMON_APPDATA": 35,
420 "CSIDL_LOCAL_APPDATA": 28,
423 buf = ctypes.create_unicode_buffer(1024)
424 ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
426 # Downgrade to short path name if have highbit chars. See
427 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
428 has_high_char = False
434 buf2 = ctypes.create_unicode_buffer(1024)
435 if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
440 if sys.platform == "win32":
442 import win32com.shell
443 _get_win_folder = _get_win_folder_with_pywin32
447 _get_win_folder = _get_win_folder_with_ctypes
449 _get_win_folder = _get_win_folder_from_registry
455 if __name__ == "__main__":
457 appauthor = "MyCompany"
459 props = ("user_data_dir", "site_data_dir",
460 "user_config_dir", "site_config_dir",
461 "user_cache_dir", "user_log_dir")
463 print("-- app dirs (with optional 'version')")
464 dirs = AppDirs(appname, appauthor, version="1.0")
466 print("%s: %s" % (prop, getattr(dirs, prop)))
468 print("\n-- app dirs (without optional 'version')")
469 dirs = AppDirs(appname, appauthor)
471 print("%s: %s" % (prop, getattr(dirs, prop)))
473 print("\n-- app dirs (without optional 'appauthor')")
474 dirs = AppDirs(appname)
476 print("%s: %s" % (prop, getattr(dirs, prop)))