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
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
1from __future__ import annotations
3import os
4import sys
5from configparser import ConfigParser
6from pathlib import Path
8from .api import PlatformDirsABC
10if sys.platform.startswith("linux"): # pragma: no branch # no op check, only to please the type checker
11 from os import getuid
12else:
14 def getuid() -> int:
15 raise RuntimeError("should only be used on Linux")
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 """
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)
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)
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)
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)
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)
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)
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")
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)
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
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")
136 return documents_dir
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)
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)
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)
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)
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)
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()
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()}")
181 if key not in parser["top"]:
182 return None
184 path = parser["top"][key].strip('"')
185 # Handle relative home paths
186 path = path.replace("$HOME", os.path.expanduser("~"))
187 return path
189 return None
192__all__ = [
193 "Unix",
194]