api.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. """Base API."""
  2. from __future__ import annotations
  3. import os
  4. from abc import ABC, abstractmethod
  5. from pathlib import Path
  6. from typing import TYPE_CHECKING
  7. if TYPE_CHECKING:
  8. from collections.abc import Iterator
  9. from typing import Literal
  10. class PlatformDirsABC(ABC): # noqa: PLR0904
  11. """Abstract base class for platform directories."""
  12. def __init__( # noqa: PLR0913, PLR0917
  13. self,
  14. appname: str | None = None,
  15. appauthor: str | Literal[False] | None = None,
  16. version: str | None = None,
  17. roaming: bool = False, # noqa: FBT001, FBT002
  18. multipath: bool = False, # noqa: FBT001, FBT002
  19. opinion: bool = True, # noqa: FBT001, FBT002
  20. ensure_exists: bool = False, # noqa: FBT001, FBT002
  21. ) -> None:
  22. """
  23. Create a new platform directory.
  24. :param appname: See `appname`.
  25. :param appauthor: See `appauthor`.
  26. :param version: See `version`.
  27. :param roaming: See `roaming`.
  28. :param multipath: See `multipath`.
  29. :param opinion: See `opinion`.
  30. :param ensure_exists: See `ensure_exists`.
  31. """
  32. self.appname = appname #: The name of application.
  33. self.appauthor = appauthor
  34. """
  35. The name of the app author or distributing body for this application.
  36. Typically, it is the owning company name. Defaults to `appname`. You may pass ``False`` to disable it.
  37. """
  38. self.version = version
  39. """
  40. An optional version path element to append to the path.
  41. You might want to use this if you want multiple versions of your app to be able to run independently. If used,
  42. this would typically be ``<major>.<minor>``.
  43. """
  44. self.roaming = roaming
  45. """
  46. Whether to use the roaming appdata directory on Windows.
  47. That means that for users on a Windows network setup for roaming profiles, this user data will be synced on
  48. login (see
  49. `here <https://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>`_).
  50. """
  51. self.multipath = multipath
  52. """
  53. An optional parameter which indicates that the entire list of data dirs should be returned.
  54. By default, the first item would only be returned.
  55. """
  56. self.opinion = opinion #: A flag to indicating to use opinionated values.
  57. self.ensure_exists = ensure_exists
  58. """
  59. Optionally create the directory (and any missing parents) upon access if it does not exist.
  60. By default, no directories are created.
  61. """
  62. def _append_app_name_and_version(self, *base: str) -> str:
  63. params = list(base[1:])
  64. if self.appname:
  65. params.append(self.appname)
  66. if self.version:
  67. params.append(self.version)
  68. path = os.path.join(base[0], *params) # noqa: PTH118
  69. self._optionally_create_directory(path)
  70. return path
  71. def _optionally_create_directory(self, path: str) -> None:
  72. if self.ensure_exists:
  73. Path(path).mkdir(parents=True, exist_ok=True)
  74. def _first_item_as_path_if_multipath(self, directory: str) -> Path:
  75. if self.multipath:
  76. # If multipath is True, the first path is returned.
  77. directory = directory.partition(os.pathsep)[0]
  78. return Path(directory)
  79. @property
  80. @abstractmethod
  81. def user_data_dir(self) -> str:
  82. """:return: data directory tied to the user"""
  83. @property
  84. @abstractmethod
  85. def site_data_dir(self) -> str:
  86. """:return: data directory shared by users"""
  87. @property
  88. @abstractmethod
  89. def user_config_dir(self) -> str:
  90. """:return: config directory tied to the user"""
  91. @property
  92. @abstractmethod
  93. def site_config_dir(self) -> str:
  94. """:return: config directory shared by the users"""
  95. @property
  96. @abstractmethod
  97. def user_cache_dir(self) -> str:
  98. """:return: cache directory tied to the user"""
  99. @property
  100. @abstractmethod
  101. def site_cache_dir(self) -> str:
  102. """:return: cache directory shared by users"""
  103. @property
  104. @abstractmethod
  105. def user_state_dir(self) -> str:
  106. """:return: state directory tied to the user"""
  107. @property
  108. @abstractmethod
  109. def user_log_dir(self) -> str:
  110. """:return: log directory tied to the user"""
  111. @property
  112. @abstractmethod
  113. def user_documents_dir(self) -> str:
  114. """:return: documents directory tied to the user"""
  115. @property
  116. @abstractmethod
  117. def user_downloads_dir(self) -> str:
  118. """:return: downloads directory tied to the user"""
  119. @property
  120. @abstractmethod
  121. def user_pictures_dir(self) -> str:
  122. """:return: pictures directory tied to the user"""
  123. @property
  124. @abstractmethod
  125. def user_videos_dir(self) -> str:
  126. """:return: videos directory tied to the user"""
  127. @property
  128. @abstractmethod
  129. def user_music_dir(self) -> str:
  130. """:return: music directory tied to the user"""
  131. @property
  132. @abstractmethod
  133. def user_desktop_dir(self) -> str:
  134. """:return: desktop directory tied to the user"""
  135. @property
  136. @abstractmethod
  137. def user_runtime_dir(self) -> str:
  138. """:return: runtime directory tied to the user"""
  139. @property
  140. @abstractmethod
  141. def site_runtime_dir(self) -> str:
  142. """:return: runtime directory shared by users"""
  143. @property
  144. def user_data_path(self) -> Path:
  145. """:return: data path tied to the user"""
  146. return Path(self.user_data_dir)
  147. @property
  148. def site_data_path(self) -> Path:
  149. """:return: data path shared by users"""
  150. return Path(self.site_data_dir)
  151. @property
  152. def user_config_path(self) -> Path:
  153. """:return: config path tied to the user"""
  154. return Path(self.user_config_dir)
  155. @property
  156. def site_config_path(self) -> Path:
  157. """:return: config path shared by the users"""
  158. return Path(self.site_config_dir)
  159. @property
  160. def user_cache_path(self) -> Path:
  161. """:return: cache path tied to the user"""
  162. return Path(self.user_cache_dir)
  163. @property
  164. def site_cache_path(self) -> Path:
  165. """:return: cache path shared by users"""
  166. return Path(self.site_cache_dir)
  167. @property
  168. def user_state_path(self) -> Path:
  169. """:return: state path tied to the user"""
  170. return Path(self.user_state_dir)
  171. @property
  172. def user_log_path(self) -> Path:
  173. """:return: log path tied to the user"""
  174. return Path(self.user_log_dir)
  175. @property
  176. def user_documents_path(self) -> Path:
  177. """:return: documents a path tied to the user"""
  178. return Path(self.user_documents_dir)
  179. @property
  180. def user_downloads_path(self) -> Path:
  181. """:return: downloads path tied to the user"""
  182. return Path(self.user_downloads_dir)
  183. @property
  184. def user_pictures_path(self) -> Path:
  185. """:return: pictures path tied to the user"""
  186. return Path(self.user_pictures_dir)
  187. @property
  188. def user_videos_path(self) -> Path:
  189. """:return: videos path tied to the user"""
  190. return Path(self.user_videos_dir)
  191. @property
  192. def user_music_path(self) -> Path:
  193. """:return: music path tied to the user"""
  194. return Path(self.user_music_dir)
  195. @property
  196. def user_desktop_path(self) -> Path:
  197. """:return: desktop path tied to the user"""
  198. return Path(self.user_desktop_dir)
  199. @property
  200. def user_runtime_path(self) -> Path:
  201. """:return: runtime path tied to the user"""
  202. return Path(self.user_runtime_dir)
  203. @property
  204. def site_runtime_path(self) -> Path:
  205. """:return: runtime path shared by users"""
  206. return Path(self.site_runtime_dir)
  207. def iter_config_dirs(self) -> Iterator[str]:
  208. """:yield: all user and site configuration directories."""
  209. yield self.user_config_dir
  210. yield self.site_config_dir
  211. def iter_data_dirs(self) -> Iterator[str]:
  212. """:yield: all user and site data directories."""
  213. yield self.user_data_dir
  214. yield self.site_data_dir
  215. def iter_cache_dirs(self) -> Iterator[str]:
  216. """:yield: all user and site cache directories."""
  217. yield self.user_cache_dir
  218. yield self.site_cache_dir
  219. def iter_runtime_dirs(self) -> Iterator[str]:
  220. """:yield: all user and site runtime directories."""
  221. yield self.user_runtime_dir
  222. yield self.site_runtime_dir
  223. def iter_config_paths(self) -> Iterator[Path]:
  224. """:yield: all user and site configuration paths."""
  225. for path in self.iter_config_dirs():
  226. yield Path(path)
  227. def iter_data_paths(self) -> Iterator[Path]:
  228. """:yield: all user and site data paths."""
  229. for path in self.iter_data_dirs():
  230. yield Path(path)
  231. def iter_cache_paths(self) -> Iterator[Path]:
  232. """:yield: all user and site cache paths."""
  233. for path in self.iter_cache_dirs():
  234. yield Path(path)
  235. def iter_runtime_paths(self) -> Iterator[Path]:
  236. """:yield: all user and site runtime paths."""
  237. for path in self.iter_runtime_dirs():
  238. yield Path(path)