Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_vendor/platformdirs/unix.py: 42%

102 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:48 +0000

1from __future__ import annotations 

2 

3import os 

4import sys 

5from configparser import ConfigParser 

6from pathlib import Path 

7 

8from .api import PlatformDirsABC 

9 

10if sys.platform.startswith("linux"): # pragma: no branch # no op check, only to please the type checker 

11 from os import getuid 

12else: 

13 

14 def getuid() -> int: 

15 raise RuntimeError("should only be used on Linux") 

16 

17 

18class Unix(PlatformDirsABC): 

19 """ 

20 On Unix/Linux, we follow the 

21 `XDG Basedir Spec <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_. The spec allows 

22 overriding directories with environment variables. The examples show are the default values, alongside the name of 

23 the environment variable that overrides them. Makes use of the 

24 `appname <platformdirs.api.PlatformDirsABC.appname>`, 

25 `version <platformdirs.api.PlatformDirsABC.version>`, 

26 `multipath <platformdirs.api.PlatformDirsABC.multipath>`, 

27 `opinion <platformdirs.api.PlatformDirsABC.opinion>`, 

28 `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`. 

29 """ 

30 

31 @property 

32 def user_data_dir(self) -> str: 

33 """ 

34 :return: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or 

35 ``$XDG_DATA_HOME/$appname/$version`` 

36 """ 

37 path = os.environ.get("XDG_DATA_HOME", "") 

38 if not path.strip(): 

39 path = os.path.expanduser("~/.local/share") 

40 return self._append_app_name_and_version(path) 

41 

42 @property 

43 def site_data_dir(self) -> str: 

44 """ 

45 :return: data directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>` is 

46 enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS 

47 path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version`` 

48 """ 

49 # XDG default for $XDG_DATA_DIRS; only first, if multipath is False 

50 path = os.environ.get("XDG_DATA_DIRS", "") 

51 if not path.strip(): 

52 path = f"/usr/local/share{os.pathsep}/usr/share" 

53 return self._with_multi_path(path) 

54 

55 def _with_multi_path(self, path: str) -> str: 

56 path_list = path.split(os.pathsep) 

57 if not self.multipath: 

58 path_list = path_list[0:1] 

59 path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list] 

60 return os.pathsep.join(path_list) 

61 

62 @property 

63 def user_config_dir(self) -> str: 

64 """ 

65 :return: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or 

66 ``$XDG_CONFIG_HOME/$appname/$version`` 

67 """ 

68 path = os.environ.get("XDG_CONFIG_HOME", "") 

69 if not path.strip(): 

70 path = os.path.expanduser("~/.config") 

71 return self._append_app_name_and_version(path) 

72 

73 @property 

74 def site_config_dir(self) -> str: 

75 """ 

76 :return: config directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>` 

77 is enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS 

78 path separator), e.g. ``/etc/xdg/$appname/$version`` 

79 """ 

80 # XDG default for $XDG_CONFIG_DIRS only first, if multipath is False 

81 path = os.environ.get("XDG_CONFIG_DIRS", "") 

82 if not path.strip(): 

83 path = "/etc/xdg" 

84 return self._with_multi_path(path) 

85 

86 @property 

87 def user_cache_dir(self) -> str: 

88 """ 

89 :return: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or 

90 ``~/$XDG_CACHE_HOME/$appname/$version`` 

91 """ 

92 path = os.environ.get("XDG_CACHE_HOME", "") 

93 if not path.strip(): 

94 path = os.path.expanduser("~/.cache") 

95 return self._append_app_name_and_version(path) 

96 

97 @property 

98 def site_cache_dir(self) -> str: 

99 """ 

100 :return: cache directory shared by users, e.g. ``/var/tmp/$appname/$version`` 

101 """ 

102 return self._append_app_name_and_version("/var/tmp") 

103 

104 @property 

105 def user_state_dir(self) -> str: 

106 """ 

107 :return: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or 

108 ``$XDG_STATE_HOME/$appname/$version`` 

109 """ 

110 path = os.environ.get("XDG_STATE_HOME", "") 

111 if not path.strip(): 

112 path = os.path.expanduser("~/.local/state") 

113 return self._append_app_name_and_version(path) 

114 

115 @property 

116 def user_log_dir(self) -> str: 

117 """ 

118 :return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it 

119 """ 

120 path = self.user_state_dir 

121 if self.opinion: 

122 path = os.path.join(path, "log") 

123 return path 

124 

125 @property 

126 def user_documents_dir(self) -> str: 

127 """ 

128 :return: documents directory tied to the user, e.g. ``~/Documents`` 

129 """ 

130 documents_dir = _get_user_dirs_folder("XDG_DOCUMENTS_DIR") 

131 if documents_dir is None: 

132 documents_dir = os.environ.get("XDG_DOCUMENTS_DIR", "").strip() 

133 if not documents_dir: 

134 documents_dir = os.path.expanduser("~/Documents") 

135 

136 return documents_dir 

137 

138 @property 

139 def user_runtime_dir(self) -> str: 

140 """ 

141 :return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or 

142 ``$XDG_RUNTIME_DIR/$appname/$version`` 

143 """ 

144 path = os.environ.get("XDG_RUNTIME_DIR", "") 

145 if not path.strip(): 

146 path = f"/run/user/{getuid()}" 

147 return self._append_app_name_and_version(path) 

148 

149 @property 

150 def site_data_path(self) -> Path: 

151 """:return: data path shared by users. Only return first item, even if ``multipath`` is set to ``True``""" 

152 return self._first_item_as_path_if_multipath(self.site_data_dir) 

153 

154 @property 

155 def site_config_path(self) -> Path: 

156 """:return: config path shared by the users. Only return first item, even if ``multipath`` is set to ``True``""" 

157 return self._first_item_as_path_if_multipath(self.site_config_dir) 

158 

159 @property 

160 def site_cache_path(self) -> Path: 

161 """:return: cache path shared by users. Only return first item, even if ``multipath`` is set to ``True``""" 

162 return self._first_item_as_path_if_multipath(self.site_cache_dir) 

163 

164 def _first_item_as_path_if_multipath(self, directory: str) -> Path: 

165 if self.multipath: 

166 # If multipath is True, the first path is returned. 

167 directory = directory.split(os.pathsep)[0] 

168 return Path(directory) 

169 

170 

171def _get_user_dirs_folder(key: str) -> str | None: 

172 """Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/""" 

173 user_dirs_config_path = os.path.join(Unix().user_config_dir, "user-dirs.dirs") 

174 if os.path.exists(user_dirs_config_path): 

175 parser = ConfigParser() 

176 

177 with open(user_dirs_config_path) as stream: 

178 # Add fake section header, so ConfigParser doesn't complain 

179 parser.read_string(f"[top]\n{stream.read()}") 

180 

181 if key not in parser["top"]: 

182 return None 

183 

184 path = parser["top"][key].strip('"') 

185 # Handle relative home paths 

186 path = path.replace("$HOME", os.path.expanduser("~")) 

187 return path 

188 

189 return None 

190 

191 

192__all__ = [ 

193 "Unix", 

194]