Videre
This commit is contained in:
@@ -0,0 +1,857 @@
|
||||
"""Utilities for determining application-specific dirs.
|
||||
|
||||
Provides convenience functions (e.g. :func:`user_data_dir`, :func:`user_config_path`), a :data:`PlatformDirs` class that
|
||||
auto-detects the current platform, and the :class:`~platformdirs.api.PlatformDirsABC` base class.
|
||||
|
||||
See <https://github.com/platformdirs/platformdirs> for details and usage.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .api import PlatformDirsABC
|
||||
from .version import __version__
|
||||
from .version import __version_tuple__ as __version_info__
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
if sys.platform == "win32":
|
||||
from platformdirs.windows import Windows as _Result
|
||||
elif sys.platform == "darwin":
|
||||
from platformdirs.macos import MacOS as _Result
|
||||
else:
|
||||
from platformdirs.unix import Unix as _Result
|
||||
|
||||
|
||||
def _set_platform_dir_class() -> type[PlatformDirsABC]:
|
||||
if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
|
||||
if os.getenv("SHELL") or os.getenv("PREFIX"):
|
||||
return _Result
|
||||
|
||||
from platformdirs.android import _android_folder # noqa: PLC0415
|
||||
|
||||
if _android_folder() is not None:
|
||||
from platformdirs.android import Android # noqa: PLC0415
|
||||
|
||||
return Android # return to avoid redefinition of a result
|
||||
|
||||
return _Result
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# Work around mypy issue: https://github.com/python/mypy/issues/10962
|
||||
PlatformDirs = _Result
|
||||
else:
|
||||
PlatformDirs = _set_platform_dir_class() #: Currently active platform
|
||||
AppDirs = PlatformDirs #: Backwards compatibility with appdirs
|
||||
|
||||
|
||||
def user_data_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: data directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_data_dir
|
||||
|
||||
|
||||
def site_data_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: data directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_data_dir
|
||||
|
||||
|
||||
def user_config_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: config directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_config_dir
|
||||
|
||||
|
||||
def site_config_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: config directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_config_dir
|
||||
|
||||
|
||||
def user_cache_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: cache directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_cache_dir
|
||||
|
||||
|
||||
def site_cache_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: cache directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_cache_dir
|
||||
|
||||
|
||||
def user_state_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: state directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_state_dir
|
||||
|
||||
|
||||
def site_state_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: state directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_state_dir
|
||||
|
||||
|
||||
def user_log_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: log directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_log_dir
|
||||
|
||||
|
||||
def site_log_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: log directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_log_dir
|
||||
|
||||
|
||||
def user_documents_dir() -> str:
|
||||
""":returns: documents directory tied to the user"""
|
||||
return PlatformDirs().user_documents_dir
|
||||
|
||||
|
||||
def user_downloads_dir() -> str:
|
||||
""":returns: downloads directory tied to the user"""
|
||||
return PlatformDirs().user_downloads_dir
|
||||
|
||||
|
||||
def user_pictures_dir() -> str:
|
||||
""":returns: pictures directory tied to the user"""
|
||||
return PlatformDirs().user_pictures_dir
|
||||
|
||||
|
||||
def user_videos_dir() -> str:
|
||||
""":returns: videos directory tied to the user"""
|
||||
return PlatformDirs().user_videos_dir
|
||||
|
||||
|
||||
def user_music_dir() -> str:
|
||||
""":returns: music directory tied to the user"""
|
||||
return PlatformDirs().user_music_dir
|
||||
|
||||
|
||||
def user_desktop_dir() -> str:
|
||||
""":returns: desktop directory tied to the user"""
|
||||
return PlatformDirs().user_desktop_dir
|
||||
|
||||
|
||||
def user_bin_dir() -> str:
|
||||
""":returns: bin directory tied to the user"""
|
||||
return PlatformDirs().user_bin_dir
|
||||
|
||||
|
||||
def site_bin_dir() -> str:
|
||||
""":returns: bin directory shared by users"""
|
||||
return PlatformDirs().site_bin_dir
|
||||
|
||||
|
||||
def user_applications_dir() -> str:
|
||||
""":returns: applications directory tied to the user"""
|
||||
return PlatformDirs().user_applications_dir
|
||||
|
||||
|
||||
def site_applications_dir(
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: applications directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_applications_dir
|
||||
|
||||
|
||||
def user_runtime_dir( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: runtime directory tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_runtime_dir
|
||||
|
||||
|
||||
def site_runtime_dir(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> str:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: runtime directory shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_runtime_dir
|
||||
|
||||
|
||||
def user_data_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: data path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_data_path
|
||||
|
||||
|
||||
def site_data_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: data path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_data_path
|
||||
|
||||
|
||||
def user_config_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: config path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_config_path
|
||||
|
||||
|
||||
def site_config_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: config path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_config_path
|
||||
|
||||
|
||||
def site_cache_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: cache path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_cache_path
|
||||
|
||||
|
||||
def user_cache_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: cache path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_cache_path
|
||||
|
||||
|
||||
def user_state_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param roaming: See `roaming <platformdirs.api.PlatformDirsABC.roaming>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: state path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
roaming=roaming,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_state_path
|
||||
|
||||
|
||||
def site_state_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: state path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_state_path
|
||||
|
||||
|
||||
def user_log_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: log path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_log_path
|
||||
|
||||
|
||||
def site_log_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: log path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_log_path
|
||||
|
||||
|
||||
def user_documents_path() -> Path:
|
||||
""":returns: documents path tied to the user"""
|
||||
return PlatformDirs().user_documents_path
|
||||
|
||||
|
||||
def user_downloads_path() -> Path:
|
||||
""":returns: downloads path tied to the user"""
|
||||
return PlatformDirs().user_downloads_path
|
||||
|
||||
|
||||
def user_pictures_path() -> Path:
|
||||
""":returns: pictures path tied to the user"""
|
||||
return PlatformDirs().user_pictures_path
|
||||
|
||||
|
||||
def user_videos_path() -> Path:
|
||||
""":returns: videos path tied to the user"""
|
||||
return PlatformDirs().user_videos_path
|
||||
|
||||
|
||||
def user_music_path() -> Path:
|
||||
""":returns: music path tied to the user"""
|
||||
return PlatformDirs().user_music_path
|
||||
|
||||
|
||||
def user_desktop_path() -> Path:
|
||||
""":returns: desktop path tied to the user"""
|
||||
return PlatformDirs().user_desktop_path
|
||||
|
||||
|
||||
def user_bin_path() -> Path:
|
||||
""":returns: bin path tied to the user"""
|
||||
return PlatformDirs().user_bin_path
|
||||
|
||||
|
||||
def site_bin_path() -> Path:
|
||||
""":returns: bin path shared by users"""
|
||||
return PlatformDirs().site_bin_path
|
||||
|
||||
|
||||
def user_applications_path() -> Path:
|
||||
""":returns: applications path tied to the user"""
|
||||
return PlatformDirs().user_applications_path
|
||||
|
||||
|
||||
def site_applications_path(
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param multipath: See `multipath <platformdirs.api.PlatformDirsABC.multipath>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: applications path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
multipath=multipath,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_applications_path
|
||||
|
||||
|
||||
def user_runtime_path( # noqa: PLR0913, PLR0917
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
:param use_site_for_root: See `use_site_for_root <platformdirs.api.PlatformDirsABC.use_site_for_root>`.
|
||||
|
||||
:returns: runtime path tied to the user
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
use_site_for_root=use_site_for_root,
|
||||
).user_runtime_path
|
||||
|
||||
|
||||
def site_runtime_path(
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
) -> Path:
|
||||
""":param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
|
||||
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
|
||||
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
|
||||
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
|
||||
:param ensure_exists: See `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
:returns: runtime path shared by users
|
||||
|
||||
"""
|
||||
return PlatformDirs(
|
||||
appname=appname,
|
||||
appauthor=appauthor,
|
||||
version=version,
|
||||
opinion=opinion,
|
||||
ensure_exists=ensure_exists,
|
||||
).site_runtime_path
|
||||
|
||||
|
||||
__all__ = [
|
||||
"AppDirs",
|
||||
"PlatformDirs",
|
||||
"PlatformDirsABC",
|
||||
"__version__",
|
||||
"__version_info__",
|
||||
"site_applications_dir",
|
||||
"site_applications_path",
|
||||
"site_bin_dir",
|
||||
"site_bin_path",
|
||||
"site_cache_dir",
|
||||
"site_cache_path",
|
||||
"site_config_dir",
|
||||
"site_config_path",
|
||||
"site_data_dir",
|
||||
"site_data_path",
|
||||
"site_log_dir",
|
||||
"site_log_path",
|
||||
"site_runtime_dir",
|
||||
"site_runtime_path",
|
||||
"site_state_dir",
|
||||
"site_state_path",
|
||||
"user_applications_dir",
|
||||
"user_applications_path",
|
||||
"user_bin_dir",
|
||||
"user_bin_path",
|
||||
"user_cache_dir",
|
||||
"user_cache_path",
|
||||
"user_config_dir",
|
||||
"user_config_path",
|
||||
"user_data_dir",
|
||||
"user_data_path",
|
||||
"user_desktop_dir",
|
||||
"user_desktop_path",
|
||||
"user_documents_dir",
|
||||
"user_documents_path",
|
||||
"user_downloads_dir",
|
||||
"user_downloads_path",
|
||||
"user_log_dir",
|
||||
"user_log_path",
|
||||
"user_music_dir",
|
||||
"user_music_path",
|
||||
"user_pictures_dir",
|
||||
"user_pictures_path",
|
||||
"user_runtime_dir",
|
||||
"user_runtime_path",
|
||||
"user_state_dir",
|
||||
"user_state_path",
|
||||
"user_videos_dir",
|
||||
"user_videos_path",
|
||||
]
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Main entry point."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from platformdirs import PlatformDirs, __version__
|
||||
|
||||
PROPS = (
|
||||
"user_data_dir",
|
||||
"user_config_dir",
|
||||
"user_cache_dir",
|
||||
"user_state_dir",
|
||||
"user_log_dir",
|
||||
"user_documents_dir",
|
||||
"user_downloads_dir",
|
||||
"user_pictures_dir",
|
||||
"user_videos_dir",
|
||||
"user_music_dir",
|
||||
"user_bin_dir",
|
||||
"site_bin_dir",
|
||||
"user_applications_dir",
|
||||
"user_runtime_dir",
|
||||
"site_data_dir",
|
||||
"site_config_dir",
|
||||
"site_cache_dir",
|
||||
"site_state_dir",
|
||||
"site_log_dir",
|
||||
"site_applications_dir",
|
||||
"site_runtime_dir",
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Run the main entry point."""
|
||||
app_name = "MyApp"
|
||||
app_author = "MyCompany"
|
||||
|
||||
print(f"-- platformdirs {__version__} --") # noqa: T201
|
||||
|
||||
print("-- app dirs (with optional 'version')") # noqa: T201
|
||||
dirs = PlatformDirs(app_name, app_author, version="1.0")
|
||||
for prop in PROPS:
|
||||
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||
|
||||
print("\n-- app dirs (without optional 'version')") # noqa: T201
|
||||
dirs = PlatformDirs(app_name, app_author)
|
||||
for prop in PROPS:
|
||||
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||
|
||||
print("\n-- app dirs (without optional 'appauthor')") # noqa: T201
|
||||
dirs = PlatformDirs(app_name)
|
||||
for prop in PROPS:
|
||||
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||
|
||||
print("\n-- app dirs (with disabled 'appauthor')") # noqa: T201
|
||||
dirs = PlatformDirs(app_name, appauthor=False)
|
||||
for prop in PROPS:
|
||||
print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,143 @@
|
||||
"""XDG environment variable mixin for Unix and macOS."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from .api import PlatformDirsABC
|
||||
|
||||
|
||||
class XDGMixin(PlatformDirsABC):
|
||||
"""Mixin that checks XDG environment variables, falling back to platform-specific defaults via ``super()``."""
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user, from ``$XDG_DATA_HOME`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_DATA_HOME", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().user_data_dir
|
||||
|
||||
@property
|
||||
def _site_data_dirs(self) -> list[str]:
|
||||
if xdg_dirs := os.environ.get("XDG_DATA_DIRS", "").strip():
|
||||
return [self._append_app_name_and_version(p) for p in xdg_dirs.split(os.pathsep) if p.strip()]
|
||||
return super()._site_data_dirs
|
||||
|
||||
@property
|
||||
def site_data_dir(self) -> str:
|
||||
""":returns: data directories shared by users, from ``$XDG_DATA_DIRS`` if set, else platform default"""
|
||||
dirs = self._site_data_dirs
|
||||
return os.pathsep.join(dirs) if self.multipath else dirs[0]
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, from ``$XDG_CONFIG_HOME`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_CONFIG_HOME", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().user_config_dir
|
||||
|
||||
@property
|
||||
def _site_config_dirs(self) -> list[str]:
|
||||
if xdg_dirs := os.environ.get("XDG_CONFIG_DIRS", "").strip():
|
||||
return [self._append_app_name_and_version(p) for p in xdg_dirs.split(os.pathsep) if p.strip()]
|
||||
return super()._site_config_dirs
|
||||
|
||||
@property
|
||||
def site_config_dir(self) -> str:
|
||||
""":returns: config directories shared by users, from ``$XDG_CONFIG_DIRS`` if set, else platform default"""
|
||||
dirs = self._site_config_dirs
|
||||
return os.pathsep.join(dirs) if self.multipath else dirs[0]
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user, from ``$XDG_CACHE_HOME`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_CACHE_HOME", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().user_cache_dir
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, from ``$XDG_STATE_HOME`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_STATE_HOME", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().user_state_dir
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user, from ``$XDG_RUNTIME_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_RUNTIME_DIR", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().user_runtime_dir
|
||||
|
||||
@property
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users, from ``$XDG_RUNTIME_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_RUNTIME_DIR", "").strip():
|
||||
return self._append_app_name_and_version(path)
|
||||
return super().site_runtime_dir
|
||||
|
||||
@property
|
||||
def user_documents_dir(self) -> str:
|
||||
""":returns: documents directory tied to the user, from ``$XDG_DOCUMENTS_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_DOCUMENTS_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_documents_dir
|
||||
|
||||
@property
|
||||
def user_downloads_dir(self) -> str:
|
||||
""":returns: downloads directory tied to the user, from ``$XDG_DOWNLOAD_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_DOWNLOAD_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_downloads_dir
|
||||
|
||||
@property
|
||||
def user_pictures_dir(self) -> str:
|
||||
""":returns: pictures directory tied to the user, from ``$XDG_PICTURES_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_PICTURES_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_pictures_dir
|
||||
|
||||
@property
|
||||
def user_videos_dir(self) -> str:
|
||||
""":returns: videos directory tied to the user, from ``$XDG_VIDEOS_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_VIDEOS_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_videos_dir
|
||||
|
||||
@property
|
||||
def user_music_dir(self) -> str:
|
||||
""":returns: music directory tied to the user, from ``$XDG_MUSIC_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_MUSIC_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_music_dir
|
||||
|
||||
@property
|
||||
def user_desktop_dir(self) -> str:
|
||||
""":returns: desktop directory tied to the user, from ``$XDG_DESKTOP_DIR`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_DESKTOP_DIR", "").strip():
|
||||
return os.path.expanduser(path) # noqa: PTH111
|
||||
return super().user_desktop_dir
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user, from ``$XDG_DATA_HOME`` if set, else platform default"""
|
||||
if path := os.environ.get("XDG_DATA_HOME", "").strip():
|
||||
return os.path.join(os.path.expanduser(path), "applications") # noqa: PTH111, PTH118
|
||||
return super().user_applications_dir
|
||||
|
||||
@property
|
||||
def _site_applications_dirs(self) -> list[str]:
|
||||
if xdg_dirs := os.environ.get("XDG_DATA_DIRS", "").strip():
|
||||
return [os.path.join(p, "applications") for p in xdg_dirs.split(os.pathsep) if p.strip()] # noqa: PTH118
|
||||
return super()._site_applications_dirs
|
||||
|
||||
@property
|
||||
def site_applications_dir(self) -> str:
|
||||
""":returns: applications directories shared by users, from ``$XDG_DATA_DIRS`` if set, else platform default"""
|
||||
dirs = self._site_applications_dirs
|
||||
return os.pathsep.join(dirs) if self.multipath else dirs[0]
|
||||
|
||||
|
||||
__all__ = [
|
||||
"XDGMixin",
|
||||
]
|
||||
@@ -0,0 +1,275 @@
|
||||
"""Android."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from .api import PlatformDirsABC
|
||||
|
||||
|
||||
class Android(PlatformDirsABC): # noqa: PLR0904
|
||||
"""Platform directories for Android.
|
||||
|
||||
Follows the guidance `from here <https://android.stackexchange.com/a/216132>`_. Directories are typically located
|
||||
under the app's private storage (``/data/user/<userid>/<packagename>/``).
|
||||
|
||||
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`, `version
|
||||
<platformdirs.api.PlatformDirsABC.version>`, `opinion <platformdirs.api.PlatformDirsABC.opinion>`, `ensure_exists
|
||||
<platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/<AppName>``"""
|
||||
return self._append_app_name_and_version(cast("str", _android_folder()), "files")
|
||||
|
||||
@property
|
||||
def site_data_dir(self) -> str:
|
||||
""":returns: data directory shared by users, same as `user_data_dir`"""
|
||||
return self.user_data_dir
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``"""
|
||||
return self._append_app_name_and_version(cast("str", _android_folder()), "shared_prefs")
|
||||
|
||||
@property
|
||||
def site_config_dir(self) -> str:
|
||||
""":returns: config directory shared by users, same as `user_config_dir`"""
|
||||
return self.user_config_dir
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user, e.g.,``/data/user/<userid>/<packagename>/cache/<AppName>``"""
|
||||
return self._append_app_name_and_version(cast("str", _android_folder()), "cache")
|
||||
|
||||
@property
|
||||
def site_cache_dir(self) -> str:
|
||||
""":returns: cache directory shared by users, same as `user_cache_dir`"""
|
||||
return self.user_cache_dir
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, same as `user_data_dir`"""
|
||||
return self.user_data_dir
|
||||
|
||||
@property
|
||||
def site_state_dir(self) -> str:
|
||||
""":returns: state directory shared by users, same as `user_state_dir`"""
|
||||
return self.user_state_dir
|
||||
|
||||
@property
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it, e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/log``"""
|
||||
path = self.user_cache_dir
|
||||
if self.opinion:
|
||||
path = os.path.join(path, "log") # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def site_log_dir(self) -> str:
|
||||
""":returns: log directory shared by users, same as `user_log_dir`"""
|
||||
return self.user_log_dir
|
||||
|
||||
@property
|
||||
def user_documents_dir(self) -> str:
|
||||
""":returns: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``"""
|
||||
return _android_documents_folder()
|
||||
|
||||
@property
|
||||
def user_downloads_dir(self) -> str:
|
||||
""":returns: downloads directory tied to the user e.g. ``/storage/emulated/0/Downloads``"""
|
||||
return _android_downloads_folder()
|
||||
|
||||
@property
|
||||
def user_pictures_dir(self) -> str:
|
||||
""":returns: pictures directory tied to the user e.g. ``/storage/emulated/0/Pictures``"""
|
||||
return _android_pictures_folder()
|
||||
|
||||
@property
|
||||
def user_videos_dir(self) -> str:
|
||||
""":returns: videos directory tied to the user e.g. ``/storage/emulated/0/DCIM/Camera``"""
|
||||
return _android_videos_folder()
|
||||
|
||||
@property
|
||||
def user_music_dir(self) -> str:
|
||||
""":returns: music directory tied to the user e.g. ``/storage/emulated/0/Music``"""
|
||||
return _android_music_folder()
|
||||
|
||||
@property
|
||||
def user_desktop_dir(self) -> str:
|
||||
""":returns: desktop directory tied to the user e.g. ``/storage/emulated/0/Desktop``"""
|
||||
return "/storage/emulated/0/Desktop"
|
||||
|
||||
@property
|
||||
def user_bin_dir(self) -> str:
|
||||
""":returns: bin directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/bin``"""
|
||||
return os.path.join(cast("str", _android_folder()), "files", "bin") # noqa: PTH118
|
||||
|
||||
@property
|
||||
def site_bin_dir(self) -> str:
|
||||
""":returns: bin directory shared by users, same as `user_bin_dir`"""
|
||||
return self.user_bin_dir
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user, same as `user_data_dir`"""
|
||||
return self.user_data_dir
|
||||
|
||||
@property
|
||||
def site_applications_dir(self) -> str:
|
||||
""":returns: applications directory shared by users, same as `user_applications_dir`"""
|
||||
return self.user_applications_dir
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it, e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/tmp``"""
|
||||
path = self.user_cache_dir
|
||||
if self.opinion:
|
||||
path = os.path.join(path, "tmp") # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||
return self.user_runtime_dir
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_folder() -> str | None: # noqa: C901
|
||||
""":returns: base folder for the Android OS or None if it cannot be found"""
|
||||
result: str | None = None
|
||||
# type checker isn't happy with our "import android", just don't do this when type checking see
|
||||
# https://stackoverflow.com/a/61394121
|
||||
if not TYPE_CHECKING:
|
||||
try:
|
||||
# First try to get a path to android app using python4android (if available)...
|
||||
from android import mActivity # noqa: PLC0415
|
||||
|
||||
context = cast("android.content.Context", mActivity.getApplicationContext()) # noqa: F821
|
||||
result = context.getFilesDir().getParentFile().getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
result = None
|
||||
if result is None:
|
||||
try:
|
||||
# ...and fall back to using plain pyjnius, if python4android isn't available or doesn't deliver any useful
|
||||
# result...
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
result = context.getFilesDir().getParentFile().getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
result = None
|
||||
if result is None:
|
||||
# and if that fails, too, find an android folder looking at path on the sys.path
|
||||
# warning: only works for apps installed under /data, not adopted storage etc.
|
||||
pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
|
||||
for path in sys.path:
|
||||
if pattern.match(path):
|
||||
result = path.split("/files")[0]
|
||||
break
|
||||
else:
|
||||
result = None
|
||||
if result is None:
|
||||
# one last try: find an android folder looking at path on the sys.path taking adopted storage paths into
|
||||
# account
|
||||
pattern = re.compile(r"/mnt/expand/[a-fA-F0-9-]{36}/(data|user/\d+)/(.+)/files")
|
||||
for path in sys.path:
|
||||
if pattern.match(path):
|
||||
result = path.split("/files")[0]
|
||||
break
|
||||
else:
|
||||
result = None
|
||||
return result
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_documents_folder() -> str:
|
||||
""":returns: documents folder for the Android OS"""
|
||||
# Get directories with pyjnius
|
||||
try:
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
environment = autoclass("android.os.Environment")
|
||||
documents_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
documents_dir = "/storage/emulated/0/Documents"
|
||||
|
||||
return documents_dir
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_downloads_folder() -> str:
|
||||
""":returns: downloads folder for the Android OS"""
|
||||
# Get directories with pyjnius
|
||||
try:
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
environment = autoclass("android.os.Environment")
|
||||
downloads_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
downloads_dir = "/storage/emulated/0/Downloads"
|
||||
|
||||
return downloads_dir
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_pictures_folder() -> str:
|
||||
""":returns: pictures folder for the Android OS"""
|
||||
# Get directories with pyjnius
|
||||
try:
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
environment = autoclass("android.os.Environment")
|
||||
pictures_dir: str = context.getExternalFilesDir(environment.DIRECTORY_PICTURES).getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
pictures_dir = "/storage/emulated/0/Pictures"
|
||||
|
||||
return pictures_dir
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_videos_folder() -> str:
|
||||
""":returns: videos folder for the Android OS"""
|
||||
# Get directories with pyjnius
|
||||
try:
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
environment = autoclass("android.os.Environment")
|
||||
videos_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DCIM).getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
videos_dir = "/storage/emulated/0/DCIM/Camera"
|
||||
|
||||
return videos_dir
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _android_music_folder() -> str:
|
||||
""":returns: music folder for the Android OS"""
|
||||
# Get directories with pyjnius
|
||||
try:
|
||||
from jnius import autoclass # noqa: PLC0415 # ty: ignore[unresolved-import]
|
||||
|
||||
context = autoclass("android.content.Context")
|
||||
environment = autoclass("android.os.Environment")
|
||||
music_dir: str = context.getExternalFilesDir(environment.DIRECTORY_MUSIC).getAbsolutePath()
|
||||
except Exception: # noqa: BLE001
|
||||
music_dir = "/storage/emulated/0/Music"
|
||||
|
||||
return music_dir
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Android",
|
||||
]
|
||||
@@ -0,0 +1,413 @@
|
||||
"""Base API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
from typing import Literal
|
||||
|
||||
|
||||
class PlatformDirsABC(ABC): # noqa: PLR0904
|
||||
"""Abstract base class defining all platform directory properties, their :class:`~pathlib.Path` variants, and iterators.
|
||||
|
||||
Platform-specific subclasses (e.g. :class:`~platformdirs.windows.Windows`, :class:`~platformdirs.macos.MacOS`,
|
||||
:class:`~platformdirs.unix.Unix`) implement the abstract properties to return the appropriate paths for each
|
||||
operating system.
|
||||
|
||||
"""
|
||||
|
||||
def __init__( # noqa: PLR0913, PLR0917
|
||||
self,
|
||||
appname: str | None = None,
|
||||
appauthor: str | Literal[False] | None = None,
|
||||
version: str | None = None,
|
||||
roaming: bool = False, # noqa: FBT001, FBT002
|
||||
multipath: bool = False, # noqa: FBT001, FBT002
|
||||
opinion: bool = True, # noqa: FBT001, FBT002
|
||||
ensure_exists: bool = False, # noqa: FBT001, FBT002
|
||||
use_site_for_root: bool = False, # noqa: FBT001, FBT002
|
||||
) -> None:
|
||||
"""Create a new platform directory.
|
||||
|
||||
:param appname: See `appname`.
|
||||
:param appauthor: See `appauthor`.
|
||||
:param version: See `version`.
|
||||
:param roaming: See `roaming`.
|
||||
:param multipath: See `multipath`.
|
||||
:param opinion: See `opinion`.
|
||||
:param ensure_exists: See `ensure_exists`.
|
||||
:param use_site_for_root: See `use_site_for_root`.
|
||||
|
||||
"""
|
||||
self.appname = appname #: The name of the application.
|
||||
self.appauthor = appauthor
|
||||
"""The name of the app author or distributing body for this application.
|
||||
|
||||
Typically, it is the owning company name. Defaults to `appname`. You may pass ``False`` to disable it.
|
||||
|
||||
.. note::
|
||||
|
||||
On Windows, the directory structure is ``<base>/<appauthor>/<appname>``. When ``appauthor`` is ``None`` (the
|
||||
default), it falls back to ``appname``, resulting in ``<base>/<appname>/<appname>`` (e.g.
|
||||
``AppData/Local/myapp/myapp``). Pass ``appauthor=False`` to omit the author directory entirely and get
|
||||
``<base>/<appname>``.
|
||||
|
||||
"""
|
||||
self.version = version
|
||||
"""An optional version path element to append to the path.
|
||||
|
||||
You might want to use this if you want multiple versions of your app to be able to run independently. If used,
|
||||
this would typically be ``<major>.<minor>``.
|
||||
|
||||
"""
|
||||
self.roaming = roaming
|
||||
"""Whether to use the roaming appdata directory on Windows.
|
||||
|
||||
That means that for users on a Windows network setup for roaming profiles, this user data will be synced on
|
||||
login (see `here <https://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>`_).
|
||||
|
||||
"""
|
||||
self.multipath = multipath
|
||||
"""An optional parameter which indicates that the entire list of data dirs should be returned.
|
||||
|
||||
By default, the first item would only be returned. Only affects ``site_data_dir`` and ``site_config_dir`` on
|
||||
Unix and macOS.
|
||||
|
||||
"""
|
||||
self.opinion = opinion
|
||||
"""Whether to use opinionated values.
|
||||
|
||||
When enabled, appends an additional subdirectory for certain directories: e.g. ``Cache`` for cache and ``Logs``
|
||||
for logs on Windows, ``log`` for logs on Unix.
|
||||
|
||||
"""
|
||||
self.ensure_exists = ensure_exists
|
||||
"""Optionally create the directory (and any missing parents) upon access if it does not exist.
|
||||
|
||||
By default, no directories are created.
|
||||
|
||||
"""
|
||||
self.use_site_for_root = use_site_for_root
|
||||
"""Whether to redirect ``user_*_dir`` calls to their ``site_*_dir`` equivalents when running as root (uid 0).
|
||||
|
||||
Only has an effect on Unix. Disabled by default for backwards compatibility. When enabled, XDG user environment
|
||||
variables (e.g. ``XDG_DATA_HOME``) are bypassed for the redirected directories.
|
||||
|
||||
"""
|
||||
|
||||
def _append_app_name_and_version(self, *base: str) -> str:
|
||||
params = list(base[1:])
|
||||
if self.appname:
|
||||
params.append(self.appname)
|
||||
if self.version:
|
||||
params.append(self.version)
|
||||
path = os.path.join(base[0], *params) # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
def _optionally_create_directory(self, path: str) -> None:
|
||||
if self.ensure_exists:
|
||||
Path(path).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def _first_item_as_path_if_multipath(self, directory: str) -> Path:
|
||||
if self.multipath:
|
||||
# If multipath is True, the first path is returned.
|
||||
directory = directory.partition(os.pathsep)[0]
|
||||
return Path(directory)
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_data_dir(self) -> str:
|
||||
""":returns: data directory shared by users"""
|
||||
|
||||
@property
|
||||
def _site_data_dirs(self) -> list[str]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_config_dir(self) -> str:
|
||||
""":returns: config directory shared by users"""
|
||||
|
||||
@property
|
||||
def _site_config_dirs(self) -> list[str]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_cache_dir(self) -> str:
|
||||
""":returns: cache directory shared by users"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_state_dir(self) -> str:
|
||||
""":returns: state directory shared by users"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_log_dir(self) -> str:
|
||||
""":returns: log directory shared by users"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_documents_dir(self) -> str:
|
||||
""":returns: documents directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_downloads_dir(self) -> str:
|
||||
""":returns: downloads directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_pictures_dir(self) -> str:
|
||||
""":returns: pictures directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_videos_dir(self) -> str:
|
||||
""":returns: videos directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_music_dir(self) -> str:
|
||||
""":returns: music directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_desktop_dir(self) -> str:
|
||||
""":returns: desktop directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_bin_dir(self) -> str:
|
||||
""":returns: bin directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_bin_dir(self) -> str:
|
||||
""":returns: bin directory shared by users"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_applications_dir(self) -> str:
|
||||
""":returns: applications directory shared by users"""
|
||||
|
||||
@property
|
||||
def _site_applications_dirs(self) -> list[str]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users"""
|
||||
|
||||
@property
|
||||
def user_data_path(self) -> Path:
|
||||
""":returns: data path tied to the user"""
|
||||
return Path(self.user_data_dir)
|
||||
|
||||
@property
|
||||
def site_data_path(self) -> Path:
|
||||
""":returns: data path shared by users"""
|
||||
return Path(self.site_data_dir)
|
||||
|
||||
@property
|
||||
def user_config_path(self) -> Path:
|
||||
""":returns: config path tied to the user"""
|
||||
return Path(self.user_config_dir)
|
||||
|
||||
@property
|
||||
def site_config_path(self) -> Path:
|
||||
""":returns: config path shared by users"""
|
||||
return Path(self.site_config_dir)
|
||||
|
||||
@property
|
||||
def user_cache_path(self) -> Path:
|
||||
""":returns: cache path tied to the user"""
|
||||
return Path(self.user_cache_dir)
|
||||
|
||||
@property
|
||||
def site_cache_path(self) -> Path:
|
||||
""":returns: cache path shared by users"""
|
||||
return Path(self.site_cache_dir)
|
||||
|
||||
@property
|
||||
def user_state_path(self) -> Path:
|
||||
""":returns: state path tied to the user"""
|
||||
return Path(self.user_state_dir)
|
||||
|
||||
@property
|
||||
def site_state_path(self) -> Path:
|
||||
""":returns: state path shared by users"""
|
||||
return Path(self.site_state_dir)
|
||||
|
||||
@property
|
||||
def user_log_path(self) -> Path:
|
||||
""":returns: log path tied to the user"""
|
||||
return Path(self.user_log_dir)
|
||||
|
||||
@property
|
||||
def site_log_path(self) -> Path:
|
||||
""":returns: log path shared by users"""
|
||||
return Path(self.site_log_dir)
|
||||
|
||||
@property
|
||||
def user_documents_path(self) -> Path:
|
||||
""":returns: documents path tied to the user"""
|
||||
return Path(self.user_documents_dir)
|
||||
|
||||
@property
|
||||
def user_downloads_path(self) -> Path:
|
||||
""":returns: downloads path tied to the user"""
|
||||
return Path(self.user_downloads_dir)
|
||||
|
||||
@property
|
||||
def user_pictures_path(self) -> Path:
|
||||
""":returns: pictures path tied to the user"""
|
||||
return Path(self.user_pictures_dir)
|
||||
|
||||
@property
|
||||
def user_videos_path(self) -> Path:
|
||||
""":returns: videos path tied to the user"""
|
||||
return Path(self.user_videos_dir)
|
||||
|
||||
@property
|
||||
def user_music_path(self) -> Path:
|
||||
""":returns: music path tied to the user"""
|
||||
return Path(self.user_music_dir)
|
||||
|
||||
@property
|
||||
def user_desktop_path(self) -> Path:
|
||||
""":returns: desktop path tied to the user"""
|
||||
return Path(self.user_desktop_dir)
|
||||
|
||||
@property
|
||||
def user_bin_path(self) -> Path:
|
||||
""":returns: bin path tied to the user"""
|
||||
return Path(self.user_bin_dir)
|
||||
|
||||
@property
|
||||
def site_bin_path(self) -> Path:
|
||||
""":returns: bin path shared by users"""
|
||||
return Path(self.site_bin_dir)
|
||||
|
||||
@property
|
||||
def user_applications_path(self) -> Path:
|
||||
""":returns: applications path tied to the user"""
|
||||
return Path(self.user_applications_dir)
|
||||
|
||||
@property
|
||||
def site_applications_path(self) -> Path:
|
||||
""":returns: applications path shared by users"""
|
||||
return Path(self.site_applications_dir)
|
||||
|
||||
@property
|
||||
def user_runtime_path(self) -> Path:
|
||||
""":returns: runtime path tied to the user"""
|
||||
return Path(self.user_runtime_dir)
|
||||
|
||||
@property
|
||||
def site_runtime_path(self) -> Path:
|
||||
""":returns: runtime path shared by users"""
|
||||
return Path(self.site_runtime_dir)
|
||||
|
||||
def iter_config_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site configuration directories."""
|
||||
yield self.user_config_dir
|
||||
yield self.site_config_dir
|
||||
|
||||
def iter_data_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site data directories."""
|
||||
yield self.user_data_dir
|
||||
yield self.site_data_dir
|
||||
|
||||
def iter_cache_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site cache directories."""
|
||||
yield self.user_cache_dir
|
||||
yield self.site_cache_dir
|
||||
|
||||
def iter_state_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site state directories."""
|
||||
yield self.user_state_dir
|
||||
yield self.site_state_dir
|
||||
|
||||
def iter_log_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site log directories."""
|
||||
yield self.user_log_dir
|
||||
yield self.site_log_dir
|
||||
|
||||
def iter_runtime_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site runtime directories."""
|
||||
yield self.user_runtime_dir
|
||||
yield self.site_runtime_dir
|
||||
|
||||
def iter_config_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site configuration paths."""
|
||||
for path in self.iter_config_dirs():
|
||||
yield Path(path)
|
||||
|
||||
def iter_data_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site data paths."""
|
||||
for path in self.iter_data_dirs():
|
||||
yield Path(path)
|
||||
|
||||
def iter_cache_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site cache paths."""
|
||||
for path in self.iter_cache_dirs():
|
||||
yield Path(path)
|
||||
|
||||
def iter_state_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site state paths."""
|
||||
for path in self.iter_state_dirs():
|
||||
yield Path(path)
|
||||
|
||||
def iter_log_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site log paths."""
|
||||
for path in self.iter_log_dirs():
|
||||
yield Path(path)
|
||||
|
||||
def iter_runtime_paths(self) -> Iterator[Path]:
|
||||
""":yield: all user and site runtime paths."""
|
||||
for path in self.iter_runtime_dirs():
|
||||
yield Path(path)
|
||||
@@ -0,0 +1,193 @@
|
||||
"""macOS."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
|
||||
from ._xdg import XDGMixin
|
||||
from .api import PlatformDirsABC
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class _MacOSDefaults(PlatformDirsABC): # noqa: PLR0904
|
||||
"""Default platform directories for macOS without XDG environment variable overrides.
|
||||
|
||||
Follows the guidance from `Apple's File System Programming Guide
|
||||
<https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html>`_.
|
||||
The XDG env var handling is in :class:`~platformdirs._xdg.XDGMixin`.
|
||||
|
||||
"""
|
||||
|
||||
def _base_user_app_support_dir(self) -> str:
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support")) # noqa: PTH111
|
||||
|
||||
def _base_site_dirs(self) -> list[str]:
|
||||
is_homebrew = "/opt/python" in sys.prefix
|
||||
homebrew_prefix = sys.prefix.split("/opt/python")[0] if is_homebrew else ""
|
||||
path_list = [self._append_app_name_and_version(f"{homebrew_prefix}/share")] if is_homebrew else []
|
||||
path_list.append(self._append_app_name_and_version("/Library/Application Support"))
|
||||
return path_list
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user, e.g. ``~/Library/Application Support/$appname/$version``"""
|
||||
return self._base_user_app_support_dir()
|
||||
|
||||
@property
|
||||
def _site_data_dirs(self) -> list[str]:
|
||||
return self._base_site_dirs()
|
||||
|
||||
@property
|
||||
def site_data_path(self) -> Path:
|
||||
""":returns: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||
return self._first_item_as_path_if_multipath(self.site_data_dir)
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, same as `user_data_dir`"""
|
||||
return self._base_user_app_support_dir()
|
||||
|
||||
@property
|
||||
def _site_config_dirs(self) -> list[str]:
|
||||
return self._base_site_dirs()
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user, e.g. ``~/Library/Caches/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_cache_dir(self) -> str:
|
||||
""":returns: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``. If we're using a Python binary managed by `Homebrew <https://brew.sh>`_, the directory will be under the Homebrew prefix, e.g. ``$homebrew_prefix/var/cache/$appname/$version``. If `multipath <platformdirs.api.PlatformDirsABC.multipath>` is enabled, and we're in Homebrew, the response is a multi-path string separated by ":", e.g. ``$homebrew_prefix/var/cache/$appname/$version:/Library/Caches/$appname/$version``"""
|
||||
is_homebrew = "/opt/python" in sys.prefix
|
||||
homebrew_prefix = sys.prefix.split("/opt/python")[0] if is_homebrew else ""
|
||||
path_list = [self._append_app_name_and_version(f"{homebrew_prefix}/var/cache")] if is_homebrew else []
|
||||
path_list.append(self._append_app_name_and_version("/Library/Caches"))
|
||||
if self.multipath:
|
||||
return os.pathsep.join(path_list)
|
||||
return path_list[0]
|
||||
|
||||
@property
|
||||
def site_cache_path(self) -> Path:
|
||||
""":returns: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||
return self._first_item_as_path_if_multipath(self.site_cache_dir)
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, same as `user_data_dir`"""
|
||||
return self._base_user_app_support_dir()
|
||||
|
||||
@property
|
||||
def site_state_dir(self) -> str:
|
||||
""":returns: state directory shared by users, same as `site_data_dir`"""
|
||||
return self._base_site_dirs()[0]
|
||||
|
||||
@property
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_log_dir(self) -> str:
|
||||
""":returns: log directory shared by users, e.g. ``/Library/Logs/$appname/$version``"""
|
||||
return self._append_app_name_and_version("/Library/Logs")
|
||||
|
||||
@property
|
||||
def user_documents_dir(self) -> str:
|
||||
""":returns: documents directory tied to the user, e.g. ``~/Documents``"""
|
||||
return os.path.expanduser("~/Documents") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_downloads_dir(self) -> str:
|
||||
""":returns: downloads directory tied to the user, e.g. ``~/Downloads``"""
|
||||
return os.path.expanduser("~/Downloads") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_pictures_dir(self) -> str:
|
||||
""":returns: pictures directory tied to the user, e.g. ``~/Pictures``"""
|
||||
return os.path.expanduser("~/Pictures") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_videos_dir(self) -> str:
|
||||
""":returns: videos directory tied to the user, e.g. ``~/Movies``"""
|
||||
return os.path.expanduser("~/Movies") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_music_dir(self) -> str:
|
||||
""":returns: music directory tied to the user, e.g. ``~/Music``"""
|
||||
return os.path.expanduser("~/Music") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_desktop_dir(self) -> str:
|
||||
""":returns: desktop directory tied to the user, e.g. ``~/Desktop``"""
|
||||
return os.path.expanduser("~/Desktop") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def user_bin_dir(self) -> str:
|
||||
""":returns: bin directory tied to the user, e.g. ``~/.local/bin``"""
|
||||
return os.path.expanduser("~/.local/bin") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_bin_dir(self) -> str:
|
||||
""":returns: bin directory shared by users, e.g. ``/usr/local/bin``"""
|
||||
return "/usr/local/bin"
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user, e.g. ``~/Applications``"""
|
||||
return os.path.expanduser("~/Applications") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def _site_applications_dirs(self) -> list[str]:
|
||||
return ["/Applications"]
|
||||
|
||||
@property
|
||||
def site_applications_dir(self) -> str:
|
||||
""":returns: applications directory shared by users, e.g. ``/Applications``"""
|
||||
dirs = self._site_applications_dirs
|
||||
return os.pathsep.join(dirs) if self.multipath else dirs[0]
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||
return self.user_runtime_dir
|
||||
|
||||
def iter_config_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site configuration directories."""
|
||||
yield self.user_config_dir
|
||||
yield from self._site_config_dirs
|
||||
|
||||
def iter_data_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site data directories."""
|
||||
yield self.user_data_dir
|
||||
yield from self._site_data_dirs
|
||||
|
||||
|
||||
class MacOS(XDGMixin, _MacOSDefaults):
|
||||
"""Platform directories for the macOS operating system.
|
||||
|
||||
Follows the guidance from `Apple documentation
|
||||
<https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html>`_.
|
||||
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`, `version
|
||||
<platformdirs.api.PlatformDirsABC.version>`, `ensure_exists <platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
XDG environment variables (e.g. ``$XDG_DATA_HOME``) are supported and take precedence over macOS defaults.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
__all__ = [
|
||||
"MacOS",
|
||||
]
|
||||
@@ -0,0 +1,296 @@
|
||||
"""Unix."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from configparser import ConfigParser
|
||||
from functools import cached_property
|
||||
from pathlib import Path
|
||||
from tempfile import gettempdir
|
||||
from typing import TYPE_CHECKING, NoReturn
|
||||
|
||||
from ._xdg import XDGMixin
|
||||
from .api import PlatformDirsABC
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
|
||||
if sys.platform == "win32":
|
||||
|
||||
def getuid() -> NoReturn:
|
||||
msg = "should only be used on Unix"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
else:
|
||||
from os import getuid
|
||||
|
||||
|
||||
class _UnixDefaults(PlatformDirsABC): # noqa: PLR0904
|
||||
"""Default directories for Unix/Linux without XDG environment variable overrides.
|
||||
|
||||
The XDG env var handling is in :class:`~platformdirs._xdg.XDGMixin`.
|
||||
|
||||
"""
|
||||
|
||||
@cached_property
|
||||
def _use_site(self) -> bool:
|
||||
return self.use_site_for_root and getuid() == 0
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or ``$XDG_DATA_HOME/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/.local/share")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def _site_data_dirs(self) -> list[str]:
|
||||
return [self._append_app_name_and_version("/usr/local/share"), self._append_app_name_and_version("/usr/share")]
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or ``$XDG_CONFIG_HOME/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/.config")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def _site_config_dirs(self) -> list[str]:
|
||||
return [self._append_app_name_and_version("/etc/xdg")]
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or ``$XDG_CACHE_HOME/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/.cache")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_cache_dir(self) -> str:
|
||||
""":returns: cache directory shared by users, e.g. ``/var/cache/$appname/$version``"""
|
||||
return self._append_app_name_and_version("/var/cache")
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or ``$XDG_STATE_HOME/$appname/$version``"""
|
||||
return self._append_app_name_and_version(os.path.expanduser("~/.local/state")) # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_state_dir(self) -> str:
|
||||
""":returns: state directory shared by users, e.g. ``/var/lib/$appname/$version``"""
|
||||
return self._append_app_name_and_version("/var/lib")
|
||||
|
||||
@property
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it"""
|
||||
path = self.user_state_dir
|
||||
if self.opinion:
|
||||
path = os.path.join(path, "log") # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def site_log_dir(self) -> str:
|
||||
""":returns: log directory shared by users, e.g. ``/var/log/$appname/$version``
|
||||
|
||||
Unlike `user_log_dir`, ``opinion`` has no effect since ``/var/log`` is inherently a log directory.
|
||||
|
||||
"""
|
||||
return self._append_app_name_and_version("/var/log")
|
||||
|
||||
@property
|
||||
def user_documents_dir(self) -> str:
|
||||
""":returns: documents directory tied to the user, e.g. ``~/Documents``"""
|
||||
return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents")
|
||||
|
||||
@property
|
||||
def user_downloads_dir(self) -> str:
|
||||
""":returns: downloads directory tied to the user, e.g. ``~/Downloads``"""
|
||||
return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads")
|
||||
|
||||
@property
|
||||
def user_pictures_dir(self) -> str:
|
||||
""":returns: pictures directory tied to the user, e.g. ``~/Pictures``"""
|
||||
return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures")
|
||||
|
||||
@property
|
||||
def user_videos_dir(self) -> str:
|
||||
""":returns: videos directory tied to the user, e.g. ``~/Videos``"""
|
||||
return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos")
|
||||
|
||||
@property
|
||||
def user_music_dir(self) -> str:
|
||||
""":returns: music directory tied to the user, e.g. ``~/Music``"""
|
||||
return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music")
|
||||
|
||||
@property
|
||||
def user_desktop_dir(self) -> str:
|
||||
""":returns: desktop directory tied to the user, e.g. ``~/Desktop``"""
|
||||
return _get_user_media_dir("XDG_DESKTOP_DIR", "~/Desktop")
|
||||
|
||||
@property
|
||||
def user_bin_dir(self) -> str:
|
||||
""":returns: bin directory tied to the user, e.g. ``~/.local/bin``"""
|
||||
return os.path.expanduser("~/.local/bin") # noqa: PTH111
|
||||
|
||||
@property
|
||||
def site_bin_dir(self) -> str:
|
||||
""":returns: bin directory shared by users, e.g. ``/usr/local/bin``"""
|
||||
return "/usr/local/bin"
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user, e.g. ``~/.local/share/applications``"""
|
||||
return os.path.join(os.path.expanduser("~/.local/share"), "applications") # noqa: PTH111, PTH118
|
||||
|
||||
@property
|
||||
def _site_applications_dirs(self) -> list[str]:
|
||||
return [os.path.join(p, "applications") for p in ["/usr/local/share", "/usr/share"]] # noqa: PTH118
|
||||
|
||||
@property
|
||||
def site_applications_dir(self) -> str:
|
||||
""":returns: applications directory shared by users, e.g. ``/usr/share/applications``"""
|
||||
dirs = self._site_applications_dirs
|
||||
return os.pathsep.join(dirs) if self.multipath else dirs[0]
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user, e.g. ``$XDG_RUNTIME_DIR/$appname/$version``.
|
||||
|
||||
If ``$XDG_RUNTIME_DIR`` is unset, tries the platform default (``/tmp/run/user/$(id -u)`` on OpenBSD, ``/var/run/user/$(id -u)`` on FreeBSD/NetBSD, ``/run/user/$(id -u)`` otherwise). If the default is not writable, falls back to a temporary directory.
|
||||
|
||||
"""
|
||||
if sys.platform.startswith("openbsd"):
|
||||
path = f"/tmp/run/user/{getuid()}" # noqa: S108
|
||||
elif sys.platform.startswith(("freebsd", "netbsd")):
|
||||
path = f"/var/run/user/{getuid()}"
|
||||
else:
|
||||
path = f"/run/user/{getuid()}"
|
||||
if not os.access(path, os.W_OK):
|
||||
path = f"{gettempdir()}/runtime-{getuid()}"
|
||||
return self._append_app_name_and_version(path)
|
||||
|
||||
@property
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users, e.g. ``/run/$appname/$version`` or ``$XDG_RUNTIME_DIR/$appname/$version``.
|
||||
|
||||
Note that this behaves almost exactly like `user_runtime_dir` if ``$XDG_RUNTIME_DIR`` is set, but will fall back to paths associated to the root user instead of a regular logged-in user if it's not set.
|
||||
|
||||
If you wish to ensure that a logged-in root user path is returned e.g. ``/run/user/0``, use `user_runtime_dir` instead.
|
||||
|
||||
For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/$appname/$version`` if ``$XDG_RUNTIME_DIR`` is not set.
|
||||
|
||||
"""
|
||||
if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
|
||||
path = "/var/run"
|
||||
else:
|
||||
path = "/run"
|
||||
return self._append_app_name_and_version(path)
|
||||
|
||||
@property
|
||||
def site_data_path(self) -> Path:
|
||||
""":returns: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||
return self._first_item_as_path_if_multipath(self.site_data_dir)
|
||||
|
||||
@property
|
||||
def site_config_path(self) -> Path:
|
||||
""":returns: config path shared by users, returns the first item, even if ``multipath`` is set to ``True``"""
|
||||
return self._first_item_as_path_if_multipath(self.site_config_dir)
|
||||
|
||||
@property
|
||||
def site_cache_path(self) -> Path:
|
||||
""":returns: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
|
||||
return self._first_item_as_path_if_multipath(self.site_cache_dir)
|
||||
|
||||
def iter_config_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site configuration directories."""
|
||||
if not self._use_site:
|
||||
yield self.user_config_dir
|
||||
yield from self._site_config_dirs
|
||||
|
||||
def iter_data_dirs(self) -> Iterator[str]:
|
||||
""":yield: all user and site data directories."""
|
||||
if not self._use_site:
|
||||
yield self.user_data_dir
|
||||
yield from self._site_data_dirs
|
||||
|
||||
|
||||
class Unix(XDGMixin, _UnixDefaults):
|
||||
"""On Unix/Linux, we follow the `XDG Basedir Spec <https://specifications.freedesktop.org/basedir/latest/>`_.
|
||||
|
||||
The spec allows overriding directories with environment variables. The examples shown are the default values,
|
||||
alongside the name of the environment variable that overrides them. Makes use of the `appname
|
||||
<platformdirs.api.PlatformDirsABC.appname>`, `version <platformdirs.api.PlatformDirsABC.version>`, `multipath
|
||||
<platformdirs.api.PlatformDirsABC.multipath>`, `opinion <platformdirs.api.PlatformDirsABC.opinion>`, `ensure_exists
|
||||
<platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
""":returns: data directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_data_dir if self._use_site else super().user_data_dir
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_config_dir if self._use_site else super().user_config_dir
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
""":returns: cache directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_cache_dir if self._use_site else super().user_cache_dir
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_state_dir if self._use_site else super().user_state_dir
|
||||
|
||||
@property
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_log_dir if self._use_site else super().user_log_dir
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
""":returns: applications directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_applications_dir if self._use_site else super().user_applications_dir
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_runtime_dir if self._use_site else super().user_runtime_dir
|
||||
|
||||
@property
|
||||
def user_bin_dir(self) -> str:
|
||||
""":returns: bin directory tied to the user, or site equivalent when root with ``use_site_for_root``"""
|
||||
return self.site_bin_dir if self._use_site else super().user_bin_dir
|
||||
|
||||
|
||||
def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
|
||||
if media_dir := _get_user_dirs_folder(env_var):
|
||||
return media_dir
|
||||
return os.path.expanduser(fallback_tilde_path) # noqa: PTH111
|
||||
|
||||
|
||||
def _get_user_dirs_folder(key: str) -> str | None:
|
||||
"""Return directory from user-dirs.dirs config file.
|
||||
|
||||
See https://freedesktop.org/wiki/Software/xdg-user-dirs/.
|
||||
|
||||
"""
|
||||
config_home = os.environ.get("XDG_CONFIG_HOME", "").strip() or os.path.expanduser("~/.config") # noqa: PTH111
|
||||
user_dirs_config_path = Path(config_home) / "user-dirs.dirs"
|
||||
if user_dirs_config_path.exists():
|
||||
parser = ConfigParser()
|
||||
|
||||
with user_dirs_config_path.open() as stream:
|
||||
parser.read_string(f"[top]\n{stream.read()}")
|
||||
|
||||
if key not in parser["top"]:
|
||||
return None
|
||||
|
||||
path = parser["top"][key].strip('"')
|
||||
return path.replace("$HOME", os.path.expanduser("~")) # noqa: PTH111
|
||||
|
||||
return None
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Unix",
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# file generated by vcs-versioning
|
||||
# don't change, don't track in version control
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"__version_tuple__",
|
||||
"version",
|
||||
"version_tuple",
|
||||
"__commit_id__",
|
||||
"commit_id",
|
||||
]
|
||||
|
||||
version: str
|
||||
__version__: str
|
||||
__version_tuple__: tuple[int | str, ...]
|
||||
version_tuple: tuple[int | str, ...]
|
||||
commit_id: str | None
|
||||
__commit_id__: str | None
|
||||
|
||||
__version__ = version = '4.9.6'
|
||||
__version_tuple__ = version_tuple = (4, 9, 6)
|
||||
|
||||
__commit_id__ = commit_id = None
|
||||
@@ -0,0 +1,369 @@
|
||||
"""Windows."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Final
|
||||
|
||||
from .api import PlatformDirsABC
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
# Not exposed by CPython; defined in the Windows SDK (shlobj_core.h)
|
||||
_KF_FLAG_DONT_VERIFY: Final[int] = 0x00004000
|
||||
|
||||
|
||||
class Windows(PlatformDirsABC): # noqa: PLR0904
|
||||
"""`MSDN on where to store app data files <https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid>`_.
|
||||
|
||||
Makes use of the `appname <platformdirs.api.PlatformDirsABC.appname>`, `appauthor
|
||||
<platformdirs.api.PlatformDirsABC.appauthor>`, `version <platformdirs.api.PlatformDirsABC.version>`, `roaming
|
||||
<platformdirs.api.PlatformDirsABC.roaming>`, `opinion <platformdirs.api.PlatformDirsABC.opinion>`, `ensure_exists
|
||||
<platformdirs.api.PlatformDirsABC.ensure_exists>`.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def user_data_dir(self) -> str:
|
||||
r""":returns: data directory tied to the user, e.g. ``%USERPROFILE%\AppData\Local\$appauthor\$appname`` (not roaming) or ``%USERPROFILE%\AppData\Roaming\$appauthor\$appname`` (roaming)"""
|
||||
const = "CSIDL_APPDATA" if self.roaming else "CSIDL_LOCAL_APPDATA"
|
||||
path = os.path.normpath(get_win_folder(const))
|
||||
return self._append_parts(path)
|
||||
|
||||
def _append_parts(self, path: str, *, opinion_value: str | None = None) -> str:
|
||||
params = []
|
||||
if self.appname:
|
||||
if self.appauthor is not False:
|
||||
author = self.appauthor or self.appname
|
||||
params.append(author)
|
||||
params.append(self.appname)
|
||||
if opinion_value is not None and self.opinion:
|
||||
params.append(opinion_value)
|
||||
if self.version:
|
||||
params.append(self.version)
|
||||
path = os.path.join(path, *params) # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def site_data_dir(self) -> str:
|
||||
r""":returns: data directory shared by users, e.g. ``C:\ProgramData\$appauthor\$appname``"""
|
||||
path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
|
||||
return self._append_parts(path)
|
||||
|
||||
@property
|
||||
def user_config_dir(self) -> str:
|
||||
""":returns: config directory tied to the user, same as `user_data_dir`"""
|
||||
return self.user_data_dir
|
||||
|
||||
@property
|
||||
def site_config_dir(self) -> str:
|
||||
""":returns: config directory shared by users, same as `site_data_dir`"""
|
||||
return self.site_data_dir
|
||||
|
||||
@property
|
||||
def user_cache_dir(self) -> str:
|
||||
r""":returns: cache directory tied to the user (if opinionated with ``Cache`` folder within ``$appname``) e.g. ``%USERPROFILE%\AppData\Local\$appauthor\$appname\Cache\$version``"""
|
||||
path = os.path.normpath(get_win_folder("CSIDL_LOCAL_APPDATA"))
|
||||
return self._append_parts(path, opinion_value="Cache")
|
||||
|
||||
@property
|
||||
def site_cache_dir(self) -> str:
|
||||
r""":returns: cache directory shared by users, e.g. ``C:\ProgramData\$appauthor\$appname\Cache\$version``"""
|
||||
path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
|
||||
return self._append_parts(path, opinion_value="Cache")
|
||||
|
||||
@property
|
||||
def user_state_dir(self) -> str:
|
||||
""":returns: state directory tied to the user, same as `user_data_dir`"""
|
||||
return self.user_data_dir
|
||||
|
||||
@property
|
||||
def site_state_dir(self) -> str:
|
||||
""":returns: state directory shared by users, same as `site_data_dir`"""
|
||||
return self.site_data_dir
|
||||
|
||||
@property
|
||||
def user_log_dir(self) -> str:
|
||||
""":returns: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it"""
|
||||
path = self.user_data_dir
|
||||
if self.opinion:
|
||||
path = os.path.join(path, "Logs") # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def site_log_dir(self) -> str:
|
||||
""":returns: log directory shared by users, same as `site_data_dir` if not opinionated else ``Logs`` in it"""
|
||||
path = self.site_data_dir
|
||||
if self.opinion:
|
||||
path = os.path.join(path, "Logs") # noqa: PTH118
|
||||
self._optionally_create_directory(path)
|
||||
return path
|
||||
|
||||
@property
|
||||
def user_documents_dir(self) -> str:
|
||||
r""":returns: documents directory tied to the user e.g. ``%USERPROFILE%\Documents``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
|
||||
|
||||
@property
|
||||
def user_downloads_dir(self) -> str:
|
||||
r""":returns: downloads directory tied to the user e.g. ``%USERPROFILE%\Downloads``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_DOWNLOADS"))
|
||||
|
||||
@property
|
||||
def user_pictures_dir(self) -> str:
|
||||
r""":returns: pictures directory tied to the user e.g. ``%USERPROFILE%\Pictures``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_MYPICTURES"))
|
||||
|
||||
@property
|
||||
def user_videos_dir(self) -> str:
|
||||
r""":returns: videos directory tied to the user e.g. ``%USERPROFILE%\Videos``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_MYVIDEO"))
|
||||
|
||||
@property
|
||||
def user_music_dir(self) -> str:
|
||||
r""":returns: music directory tied to the user e.g. ``%USERPROFILE%\Music``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_MYMUSIC"))
|
||||
|
||||
@property
|
||||
def user_desktop_dir(self) -> str:
|
||||
r""":returns: desktop directory tied to the user, e.g. ``%USERPROFILE%\Desktop``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_DESKTOPDIRECTORY"))
|
||||
|
||||
@property
|
||||
def user_bin_dir(self) -> str:
|
||||
r""":returns: bin directory tied to the user, e.g. ``%LOCALAPPDATA%\Programs``"""
|
||||
return os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Programs")) # noqa: PTH118
|
||||
|
||||
@property
|
||||
def site_bin_dir(self) -> str:
|
||||
""":returns: bin directory shared by users, e.g. ``C:\\ProgramData\bin``"""
|
||||
return os.path.normpath(os.path.join(get_win_folder("CSIDL_COMMON_APPDATA"), "bin")) # noqa: PTH118
|
||||
|
||||
@property
|
||||
def user_applications_dir(self) -> str:
|
||||
r""":returns: applications directory tied to the user, e.g. ``Start Menu\Programs``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_PROGRAMS"))
|
||||
|
||||
@property
|
||||
def site_applications_dir(self) -> str:
|
||||
r""":returns: applications directory shared by users, e.g. ``C:\ProgramData\Microsoft\Windows\Start Menu\Programs``"""
|
||||
return os.path.normpath(get_win_folder("CSIDL_COMMON_PROGRAMS"))
|
||||
|
||||
@property
|
||||
def user_runtime_dir(self) -> str:
|
||||
r""":returns: runtime directory tied to the user, e.g. ``%USERPROFILE%\AppData\Local\Temp\$appauthor\$appname``"""
|
||||
path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp")) # noqa: PTH118
|
||||
return self._append_parts(path)
|
||||
|
||||
@property
|
||||
def site_runtime_dir(self) -> str:
|
||||
""":returns: runtime directory shared by users, same as `user_runtime_dir`"""
|
||||
return self.user_runtime_dir
|
||||
|
||||
|
||||
def get_win_folder_from_env_vars(csidl_name: str) -> str:
|
||||
"""Get folder from environment variables."""
|
||||
result = get_win_folder_if_csidl_name_not_env_var(csidl_name)
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
env_var_name = {
|
||||
"CSIDL_APPDATA": "APPDATA",
|
||||
"CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
|
||||
"CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
|
||||
}.get(csidl_name)
|
||||
if env_var_name is None:
|
||||
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||
raise ValueError(msg)
|
||||
result = os.environ.get(env_var_name)
|
||||
if result is None:
|
||||
msg = f"Unset environment variable: {env_var_name}"
|
||||
raise ValueError(msg)
|
||||
return result
|
||||
|
||||
|
||||
def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None: # noqa: PLR0911
|
||||
"""Get a folder for a CSIDL name that does not exist as an environment variable."""
|
||||
if csidl_name == "CSIDL_PERSONAL":
|
||||
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents") # noqa: PTH118
|
||||
|
||||
if csidl_name == "CSIDL_DOWNLOADS":
|
||||
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads") # noqa: PTH118
|
||||
|
||||
if csidl_name == "CSIDL_MYPICTURES":
|
||||
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures") # noqa: PTH118
|
||||
|
||||
if csidl_name == "CSIDL_MYVIDEO":
|
||||
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos") # noqa: PTH118
|
||||
|
||||
if csidl_name == "CSIDL_MYMUSIC":
|
||||
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Music") # noqa: PTH118
|
||||
|
||||
if csidl_name == "CSIDL_PROGRAMS":
|
||||
return os.path.join( # noqa: PTH118
|
||||
os.path.normpath(os.environ["APPDATA"]),
|
||||
"Microsoft",
|
||||
"Windows",
|
||||
"Start Menu",
|
||||
"Programs",
|
||||
)
|
||||
|
||||
if csidl_name == "CSIDL_COMMON_PROGRAMS":
|
||||
return os.path.join( # noqa: PTH118
|
||||
os.path.normpath(os.environ.get("PROGRAMDATA", os.environ.get("ALLUSERSPROFILE", "C:\\ProgramData"))),
|
||||
"Microsoft",
|
||||
"Windows",
|
||||
"Start Menu",
|
||||
"Programs",
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def get_win_folder_from_registry(csidl_name: str) -> str:
|
||||
"""Get folder from the registry.
|
||||
|
||||
This is a fallback technique at best. I'm not sure if using the registry for these guarantees us the correct answer
|
||||
for all CSIDL_* names.
|
||||
|
||||
"""
|
||||
machine_names = {
|
||||
"CSIDL_COMMON_APPDATA",
|
||||
"CSIDL_COMMON_PROGRAMS",
|
||||
}
|
||||
shell_folder_name = {
|
||||
"CSIDL_APPDATA": "AppData",
|
||||
"CSIDL_COMMON_APPDATA": "Common AppData",
|
||||
"CSIDL_LOCAL_APPDATA": "Local AppData",
|
||||
"CSIDL_PERSONAL": "Personal",
|
||||
"CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}",
|
||||
"CSIDL_MYPICTURES": "My Pictures",
|
||||
"CSIDL_MYVIDEO": "My Video",
|
||||
"CSIDL_MYMUSIC": "My Music",
|
||||
"CSIDL_PROGRAMS": "Programs",
|
||||
"CSIDL_COMMON_PROGRAMS": "Common Programs",
|
||||
}.get(csidl_name)
|
||||
if shell_folder_name is None:
|
||||
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||
raise ValueError(msg)
|
||||
if sys.platform != "win32": # only needed for mypy type checker to know that this code runs only on Windows
|
||||
raise NotImplementedError
|
||||
import winreg # noqa: PLC0415
|
||||
|
||||
# Use HKEY_LOCAL_MACHINE for system-wide folders, HKEY_CURRENT_USER for user-specific folders
|
||||
hkey = winreg.HKEY_LOCAL_MACHINE if csidl_name in machine_names else winreg.HKEY_CURRENT_USER
|
||||
|
||||
key = winreg.OpenKey(hkey, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
|
||||
directory, _ = winreg.QueryValueEx(key, shell_folder_name)
|
||||
return str(directory)
|
||||
|
||||
|
||||
_KNOWN_FOLDER_GUIDS: dict[str, str] = {
|
||||
"CSIDL_APPDATA": "{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}",
|
||||
"CSIDL_COMMON_APPDATA": "{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}",
|
||||
"CSIDL_LOCAL_APPDATA": "{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}",
|
||||
"CSIDL_PERSONAL": "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}",
|
||||
"CSIDL_MYPICTURES": "{33E28130-4E1E-4676-835A-98395C3BC3BB}",
|
||||
"CSIDL_MYVIDEO": "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}",
|
||||
"CSIDL_MYMUSIC": "{4BD8D571-6D19-48D3-BE97-422220080E43}",
|
||||
"CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}",
|
||||
"CSIDL_DESKTOPDIRECTORY": "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}",
|
||||
"CSIDL_PROGRAMS": "{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}",
|
||||
"CSIDL_COMMON_PROGRAMS": "{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}",
|
||||
}
|
||||
|
||||
|
||||
def get_win_folder_via_ctypes(csidl_name: str) -> str:
|
||||
"""Get folder via :func:`SHGetKnownFolderPath`.
|
||||
|
||||
See https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath.
|
||||
|
||||
"""
|
||||
if sys.platform != "win32": # only needed for type checker to know that this code runs only on Windows
|
||||
raise NotImplementedError
|
||||
from ctypes import HRESULT, POINTER, Structure, WinDLL, byref, create_unicode_buffer, wintypes # noqa: PLC0415
|
||||
|
||||
class _GUID(Structure):
|
||||
_fields_ = [
|
||||
("Data1", wintypes.DWORD),
|
||||
("Data2", wintypes.WORD),
|
||||
("Data3", wintypes.WORD),
|
||||
("Data4", wintypes.BYTE * 8),
|
||||
]
|
||||
|
||||
ole32 = WinDLL("ole32")
|
||||
ole32.CLSIDFromString.restype = HRESULT
|
||||
ole32.CLSIDFromString.argtypes = [wintypes.LPCOLESTR, POINTER(_GUID)]
|
||||
ole32.CoTaskMemFree.restype = None
|
||||
ole32.CoTaskMemFree.argtypes = [wintypes.LPVOID]
|
||||
|
||||
shell32 = WinDLL("shell32")
|
||||
shell32.SHGetKnownFolderPath.restype = HRESULT
|
||||
shell32.SHGetKnownFolderPath.argtypes = [POINTER(_GUID), wintypes.DWORD, wintypes.HANDLE, POINTER(wintypes.LPWSTR)]
|
||||
|
||||
kernel32 = WinDLL("kernel32")
|
||||
kernel32.GetShortPathNameW.restype = wintypes.DWORD
|
||||
kernel32.GetShortPathNameW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR, wintypes.DWORD]
|
||||
|
||||
folder_guid = _KNOWN_FOLDER_GUIDS.get(csidl_name)
|
||||
if folder_guid is None:
|
||||
msg = f"Unknown CSIDL name: {csidl_name}"
|
||||
raise ValueError(msg)
|
||||
|
||||
guid = _GUID()
|
||||
ole32.CLSIDFromString(folder_guid, byref(guid))
|
||||
|
||||
path_ptr = wintypes.LPWSTR()
|
||||
shell32.SHGetKnownFolderPath(byref(guid), _KF_FLAG_DONT_VERIFY, None, byref(path_ptr))
|
||||
result = path_ptr.value
|
||||
ole32.CoTaskMemFree(path_ptr)
|
||||
|
||||
if result is None:
|
||||
msg = f"SHGetKnownFolderPath returned NULL for {csidl_name}"
|
||||
raise ValueError(msg)
|
||||
|
||||
if any(ord(c) > 255 for c in result): # noqa: PLR2004
|
||||
buf = create_unicode_buffer(1024)
|
||||
if kernel32.GetShortPathNameW(result, buf, 1024):
|
||||
result = buf.value
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _pick_get_win_folder() -> Callable[[str], str]:
|
||||
"""Select the best method to resolve Windows folder paths: ctypes, then registry, then environment variables."""
|
||||
try:
|
||||
import ctypes # noqa: PLC0415, F401
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
return get_win_folder_via_ctypes
|
||||
try:
|
||||
import winreg # noqa: PLC0415, F401
|
||||
except ImportError:
|
||||
return get_win_folder_from_env_vars
|
||||
else:
|
||||
return get_win_folder_from_registry
|
||||
|
||||
|
||||
_resolve_win_folder = _pick_get_win_folder()
|
||||
|
||||
|
||||
def get_win_folder(csidl_name: str) -> str:
|
||||
"""Get a Windows folder path, checking for ``WIN_PD_OVERRIDE_*`` environment variable overrides first.
|
||||
|
||||
For example, ``CSIDL_LOCAL_APPDATA`` can be overridden by setting ``WIN_PD_OVERRIDE_LOCAL_APPDATA``.
|
||||
|
||||
"""
|
||||
env_var = f"WIN_PD_OVERRIDE_{csidl_name.removeprefix('CSIDL_')}"
|
||||
if override := os.environ.get(env_var, "").strip():
|
||||
return override
|
||||
return _resolve_win_folder(csidl_name)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Windows",
|
||||
]
|
||||
Reference in New Issue
Block a user