Skip to content

Commit

Permalink
Add convenience methods to PlatformDirsAPI that allow iterating ove…
Browse files Browse the repository at this point in the history
…r both user and site dirs/paths. (#258)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bernát Gábor <gaborjbernat@gmail.com>
  • Loading branch information
3 people committed Jan 31, 2024
1 parent 0d8beea commit bc4d114
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
@@ -1,6 +1,10 @@
platformdirs Changelog
======================

platformdirs 4.1.0 (2024-01-XX)
-------------------------------
- Add convenience methods ``iter_{config,cache,data,runtime}_{dirs,paths}``.

platformdirs 4.0.0 (2023-11-10)
-------------------------------
- UNIX: revert site_cache_dir to use ``/var/cache`` instead of ``/var/tmp``
Expand Down
42 changes: 41 additions & 1 deletion src/platformdirs/api.py
Expand Up @@ -8,7 +8,7 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Literal
from typing import Iterator, Literal


class PlatformDirsABC(ABC):
Expand Down Expand Up @@ -237,3 +237,43 @@ def user_runtime_path(self) -> Path:
def site_runtime_path(self) -> Path:
""":return: 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_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_runtime_paths(self) -> Iterator[Path]:
""":yield: all user and site runtime paths."""
for path in self.iter_runtime_dirs():
yield Path(path)
46 changes: 32 additions & 14 deletions src/platformdirs/unix.py
Expand Up @@ -6,6 +6,7 @@
import sys
from configparser import ConfigParser
from pathlib import Path
from typing import Iterator

from .api import PlatformDirsABC

Expand Down Expand Up @@ -43,6 +44,13 @@ def user_data_dir(self) -> str:
path = os.path.expanduser("~/.local/share") # noqa: PTH111
return self._append_app_name_and_version(path)

@property
def _site_data_dirs(self) -> list[str]:
path = os.environ.get("XDG_DATA_DIRS", "")
if not path.strip():
path = f"/usr/local/share{os.pathsep}/usr/share"
return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]

@property
def site_data_dir(self) -> str:
"""
Expand All @@ -51,17 +59,10 @@ def site_data_dir(self) -> str:
OS path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
"""
# XDG default for $XDG_DATA_DIRS; only first, if multipath is False
path = os.environ.get("XDG_DATA_DIRS", "")
if not path.strip():
path = f"/usr/local/share{os.pathsep}/usr/share"
return self._with_multi_path(path)

def _with_multi_path(self, path: str) -> str:
path_list = path.split(os.pathsep)
dirs = self._site_data_dirs
if not self.multipath:
path_list = path_list[0:1]
path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list] # noqa: PTH111
return os.pathsep.join(path_list)
return dirs[0]
return os.pathsep.join(dirs)

@property
def user_config_dir(self) -> str:
Expand All @@ -74,6 +75,13 @@ def user_config_dir(self) -> str:
path = os.path.expanduser("~/.config") # noqa: PTH111
return self._append_app_name_and_version(path)

@property
def _site_config_dirs(self) -> list[str]:
path = os.environ.get("XDG_CONFIG_DIRS", "")
if not path.strip():
path = "/etc/xdg"
return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]

@property
def site_config_dir(self) -> str:
"""
Expand All @@ -82,10 +90,10 @@ def site_config_dir(self) -> str:
the OS path separator), e.g. ``/etc/xdg/$appname/$version``
"""
# XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
path = os.environ.get("XDG_CONFIG_DIRS", "")
if not path.strip():
path = "/etc/xdg"
return self._with_multi_path(path)
dirs = self._site_config_dirs
if not self.multipath:
return dirs[0]
return os.pathsep.join(dirs)

@property
def user_cache_dir(self) -> str:
Expand Down Expand Up @@ -216,6 +224,16 @@ def _first_item_as_path_if_multipath(self, directory: str) -> Path:
directory = directory.split(os.pathsep)[0]
return Path(directory)

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


def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
media_dir = _get_user_dirs_folder(env_var)
Expand Down

0 comments on commit bc4d114

Please sign in to comment.