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