]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/platformdirs/unix.py
1d0174f22687ed131e3244180c472b83278b8201
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / platformdirs / unix.py
1 """Unix."""
2 from __future__ import annotations
3
4 import os
5 import sys
6 from configparser import ConfigParser
7 from pathlib import Path
8
9 from .api import PlatformDirsABC
10
11 if sys.platform == "win32":
12
13 def getuid() -> int:
14 msg = "should only be used on Unix"
15 raise RuntimeError(msg)
16
17 else:
18 from os import getuid
19
20
21 class Unix(PlatformDirsABC):
22 """
23 On Unix/Linux, we follow the
24 `XDG Basedir Spec <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_. The spec allows
25 overriding directories with environment variables. The examples show are the default values, alongside the name of
26 the environment variable that overrides them. Makes use of the
27 `appname <platformdirs.api.PlatformDirsABC.appname>`,
28 `version <platformdirs.api.PlatformDirsABC.version>`,
29 `multipath <platformdirs.api.PlatformDirsABC.multipath>`,
30 `opinion <platformdirs.api.PlatformDirsABC.opinion>`,
31 `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
32 """
33
34 @property
35 def user_data_dir(self) -> str:
36 """
37 :return: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or
38 ``$XDG_DATA_HOME/$appname/$version``
39 """
40 path = os.environ.get("XDG_DATA_HOME", "")
41 if not path.strip():
42 path = os.path.expanduser("~/.local/share") # noqa: PTH111
43 return self._append_app_name_and_version(path)
44
45 @property
46 def site_data_dir(self) -> str:
47 """
48 :return: data directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>` is
49 enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS
50 path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
51 """
52 # XDG default for $XDG_DATA_DIRS; only first, if multipath is False
53 path = os.environ.get("XDG_DATA_DIRS", "")
54 if not path.strip():
55 path = f"/usr/local/share{os.pathsep}/usr/share"
56 return self._with_multi_path(path)
57
58 def _with_multi_path(self, path: str) -> str:
59 path_list = path.split(os.pathsep)
60 if not self.multipath:
61 path_list = path_list[0:1]
62 path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list] # noqa: PTH111
63 return os.pathsep.join(path_list)
64
65 @property
66 def user_config_dir(self) -> str:
67 """
68 :return: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or
69 ``$XDG_CONFIG_HOME/$appname/$version``
70 """
71 path = os.environ.get("XDG_CONFIG_HOME", "")
72 if not path.strip():
73 path = os.path.expanduser("~/.config") # noqa: PTH111
74 return self._append_app_name_and_version(path)
75
76 @property
77 def site_config_dir(self) -> str:
78 """
79 :return: config directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>`
80 is enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS
81 path separator), e.g. ``/etc/xdg/$appname/$version``
82 """
83 # XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
84 path = os.environ.get("XDG_CONFIG_DIRS", "")
85 if not path.strip():
86 path = "/etc/xdg"
87 return self._with_multi_path(path)
88
89 @property
90 def user_cache_dir(self) -> str:
91 """
92 :return: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or
93 ``~/$XDG_CACHE_HOME/$appname/$version``
94 """
95 path = os.environ.get("XDG_CACHE_HOME", "")
96 if not path.strip():
97 path = os.path.expanduser("~/.cache") # noqa: PTH111
98 return self._append_app_name_and_version(path)
99
100 @property
101 def site_cache_dir(self) -> str:
102 """:return: cache directory shared by users, e.g. ``/var/tmp/$appname/$version``"""
103 return self._append_app_name_and_version("/var/tmp") # noqa: S108
104
105 @property
106 def user_state_dir(self) -> str:
107 """
108 :return: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or
109 ``$XDG_STATE_HOME/$appname/$version``
110 """
111 path = os.environ.get("XDG_STATE_HOME", "")
112 if not path.strip():
113 path = os.path.expanduser("~/.local/state") # noqa: PTH111
114 return self._append_app_name_and_version(path)
115
116 @property
117 def user_log_dir(self) -> str:
118 """:return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it"""
119 path = self.user_state_dir
120 if self.opinion:
121 path = os.path.join(path, "log") # noqa: PTH118
122 self._optionally_create_directory(path)
123 return path
124
125 @property
126 def user_documents_dir(self) -> str:
127 """:return: documents directory tied to the user, e.g. ``~/Documents``"""
128 return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents")
129
130 @property
131 def user_downloads_dir(self) -> str:
132 """:return: downloads directory tied to the user, e.g. ``~/Downloads``"""
133 return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads")
134
135 @property
136 def user_pictures_dir(self) -> str:
137 """:return: pictures directory tied to the user, e.g. ``~/Pictures``"""
138 return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures")
139
140 @property
141 def user_videos_dir(self) -> str:
142 """:return: videos directory tied to the user, e.g. ``~/Videos``"""
143 return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos")
144
145 @property
146 def user_music_dir(self) -> str:
147 """:return: music directory tied to the user, e.g. ``~/Music``"""
148 return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music")
149
150 @property
151 def user_desktop_dir(self) -> str:
152 """:return: desktop directory tied to the user, e.g. ``~/Desktop``"""
153 return _get_user_media_dir("XDG_DESKTOP_DIR", "~/Desktop")
154
155 @property
156 def user_runtime_dir(self) -> str:
157 """
158 :return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or
159 ``$XDG_RUNTIME_DIR/$appname/$version``.
160
161 For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/user/$(id -u)/$appname/$version`` if
162 exists, otherwise ``/tmp/runtime-$(id -u)/$appname/$version``, if``$XDG_RUNTIME_DIR``
163 is not set.
164 """
165 path = os.environ.get("XDG_RUNTIME_DIR", "")
166 if not path.strip():
167 if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
168 path = f"/var/run/user/{getuid()}"
169 if not Path(path).exists():
170 path = f"/tmp/runtime-{getuid()}" # noqa: S108
171 else:
172 path = f"/run/user/{getuid()}"
173 return self._append_app_name_and_version(path)
174
175 @property
176 def site_runtime_dir(self) -> str:
177 """
178 :return: runtime directory shared by users, e.g. ``/run/$appname/$version`` or \
179 ``$XDG_RUNTIME_DIR/$appname/$version``.
180
181 Note that this behaves almost exactly like `user_runtime_dir` if ``$XDG_RUNTIME_DIR`` is set, but will
182 fall back to paths associated to the root user instead of a regular logged-in user if it's not set.
183
184 If you wish to ensure that a logged-in root user path is returned e.g. ``/run/user/0``, use `user_runtime_dir`
185 instead.
186
187 For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/$appname/$version`` if ``$XDG_RUNTIME_DIR`` is not set.
188 """
189 path = os.environ.get("XDG_RUNTIME_DIR", "")
190 if not path.strip():
191 if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
192 path = "/var/run"
193 else:
194 path = "/run"
195 return self._append_app_name_and_version(path)
196
197 @property
198 def site_data_path(self) -> Path:
199 """:return: data path shared by users. Only return first item, even if ``multipath`` is set to ``True``"""
200 return self._first_item_as_path_if_multipath(self.site_data_dir)
201
202 @property
203 def site_config_path(self) -> Path:
204 """:return: config path shared by the users. Only return first item, even if ``multipath`` is set to ``True``"""
205 return self._first_item_as_path_if_multipath(self.site_config_dir)
206
207 @property
208 def site_cache_path(self) -> Path:
209 """:return: cache path shared by users. Only return first item, even if ``multipath`` is set to ``True``"""
210 return self._first_item_as_path_if_multipath(self.site_cache_dir)
211
212 def _first_item_as_path_if_multipath(self, directory: str) -> Path:
213 if self.multipath:
214 # If multipath is True, the first path is returned.
215 directory = directory.split(os.pathsep)[0]
216 return Path(directory)
217
218
219 def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
220 media_dir = _get_user_dirs_folder(env_var)
221 if media_dir is None:
222 media_dir = os.environ.get(env_var, "").strip()
223 if not media_dir:
224 media_dir = os.path.expanduser(fallback_tilde_path) # noqa: PTH111
225
226 return media_dir
227
228
229 def _get_user_dirs_folder(key: str) -> str | None:
230 """Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/."""
231 user_dirs_config_path = Path(Unix().user_config_dir) / "user-dirs.dirs"
232 if user_dirs_config_path.exists():
233 parser = ConfigParser()
234
235 with user_dirs_config_path.open() as stream:
236 # Add fake section header, so ConfigParser doesn't complain
237 parser.read_string(f"[top]\n{stream.read()}")
238
239 if key not in parser["top"]:
240 return None
241
242 path = parser["top"][key].strip('"')
243 # Handle relative home paths
244 return path.replace("$HOME", os.path.expanduser("~")) # noqa: PTH111
245
246 return None
247
248
249 __all__ = [
250 "Unix",
251 ]