Skip to content

Commit

Permalink
Add API calls that return pathlib.Path instead of str objects (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
papr authored Jul 23, 2021
1 parent 6fe8168 commit df07a00
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ platformdirs 2.1.0
:class:`PlatformDirsABC <platformdirs.api.PlatformDirsABC>` and it's implementations:
:class:`Android <platformdirs.android.Android>`, :class:`MacOS <platformdirs.macos.MacOS>`,
:class:`Unix <platformdirs.unix.Unix>` and :class:`Windows <platformdirs.windows.Windows>`
- Add ``*_path`` API, returning :class:`pathlib.Path <pathlib.Path>` objects instead of :class:`str`
(``user_data_path``, ``user_config_path``, ``user_cache_path``, ``user_state_path``, ``user_log_path``,
``site_data_path``, ``site_config_path``) - by `@papr <https://github.com/papr/>`_

platformdirs 2.0.2
------------------
Expand Down
7 changes: 7 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,31 @@ User data directory
-------------------

.. autofunction:: platformdirs.user_data_dir
.. autofunction:: platformdirs.user_data_path

User config directory
---------------------

.. autofunction:: platformdirs.user_config_dir
.. autofunction:: platformdirs.user_config_path

Cache directory
-------------------

.. autofunction:: platformdirs.user_cache_dir
.. autofunction:: platformdirs.user_cache_path

State directory
-------------------

.. autofunction:: platformdirs.user_state_dir
.. autofunction:: platformdirs.user_state_path

Logs directory
-------------------

.. autofunction:: platformdirs.user_log_dir
.. autofunction:: platformdirs.user_log_path

Shared directories
~~~~~~~~~~~~~~~~~~
Expand All @@ -40,11 +45,13 @@ Shared data directory
---------------------

.. autofunction:: platformdirs.site_data_dir
.. autofunction:: platformdirs.site_data_path

Shared config directory
-----------------------

.. autofunction:: platformdirs.site_config_dir
.. autofunction:: platformdirs.site_config_path

Platforms
~~~~~~~~~
Expand Down
120 changes: 120 additions & 0 deletions src/platformdirs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import importlib
import os
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Optional, Type, Union

if TYPE_CHECKING:
Expand Down Expand Up @@ -143,6 +144,118 @@ def user_log_dir(
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_dir


def user_data_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
roaming: bool = False,
) -> 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.version>`.
:returns: data path tied to the user
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_data_path


def site_data_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
multipath: bool = False,
) -> 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>`.
:returns: data path shared by users
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_data_path


def user_config_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
roaming: bool = False,
) -> 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.version>`.
:returns: config path tied to the user
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_config_path


def site_config_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
multipath: bool = False,
) -> 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 `roaming <platformdirs.api.PlatformDirsABC.multipath>`.
:returns: config path shared by the users
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_config_path


def user_cache_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
opinion: bool = True,
) -> 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 `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
:returns: cache path tied to the user
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_cache_path


def user_state_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
roaming: bool = False,
) -> 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.version>`.
:returns: state path tied to the user
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_state_path


def user_log_path(
appname: Optional[str] = None,
appauthor: Union[str, None, "Literal[False]"] = None,
version: Optional[str] = None,
opinion: bool = True,
) -> 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 `roaming <platformdirs.api.PlatformDirsABC.opinion>`.
:returns: log path tied to the user
"""
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_path


__all__ = [
"__version__",
"__version_info__",
Expand All @@ -156,4 +269,11 @@ def user_log_dir(
"user_log_dir",
"site_data_dir",
"site_config_dir",
"user_data_path",
"user_config_path",
"user_cache_path",
"user_state_path",
"user_log_path",
"site_data_path",
"site_config_path",
]
36 changes: 36 additions & 0 deletions src/platformdirs/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import sys
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Optional, Union

if sys.version_info >= (3, 8): # pragma: no branch
Expand Down Expand Up @@ -97,3 +98,38 @@ def user_state_dir(self) -> str:
@abstractmethod
def user_log_dir(self) -> str:
""":return: log directory tied to the user"""

@property
def user_data_path(self) -> Path:
""":return: data path tied to the user"""
return Path(self.user_data_dir)

@property
def site_data_path(self) -> Path:
""":return: data path shared by users"""
return Path(self.site_data_dir)

@property
def user_config_path(self) -> Path:
""":return: config path tied to the user"""
return Path(self.user_config_dir)

@property
def site_config_path(self) -> Path:
""":return: config path shared by the users"""
return Path(self.site_config_dir)

@property
def user_cache_path(self) -> Path:
""":return: cache path tied to the user"""
return Path(self.user_cache_dir)

@property
def user_state_path(self) -> Path:
""":return: state path tied to the user"""
return Path(self.user_state_dir)

@property
def user_log_path(self) -> Path:
""":return: log path tied to the user"""
return Path(self.user_log_dir)
18 changes: 17 additions & 1 deletion src/platformdirs/unix.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from pathlib import Path

from .api import PlatformDirsABC

Expand Down Expand Up @@ -66,7 +67,6 @@ def site_config_dir(self) -> str:
:return: config directories shared by users (if `multipath <platformdirs.api.PlatformDirsABC.multipath>`
is enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS
path separator), e.g. ``/etc/xdg/$appname/$version``
:return:
"""
# XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
if "XDG_CONFIG_DIRS" in os.environ:
Expand Down Expand Up @@ -109,6 +109,22 @@ def user_log_dir(self) -> str:
path = os.path.join(path, "log")
return path

@property
def site_data_path(self) -> Path:
""":return: data path shared by users. Only return 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:
""":return: config path shared by the users. Only return first item, even if ``multipath`` is set to ``True``"""
return self._first_item_as_path_if_multipath(self.site_config_dir)

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.split(os.pathsep)[0]
return Path(directory)


__all__ = [
"Unix",
Expand Down
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ def func(request: SubRequest) -> str:
return cast(str, request.param)


@pytest.fixture(params=PROPS)
def func_path(request: SubRequest) -> str:
prop = cast(str, request.param)
prop = prop.replace("_dir", "_path")
return prop


@pytest.fixture()
def props() -> Tuple[str, ...]:
return PROPS
24 changes: 24 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import inspect
from pathlib import Path
from typing import Optional

import pytest
Expand All @@ -24,6 +26,28 @@ def test_property_result_is_str(func: str) -> None:
assert isinstance(result, str)


def test_method_result_is_path(func_path: str) -> None:
method = getattr(platformdirs, func_path)
result = method("MyApp", "MyCompany")
assert isinstance(result, Path)


def test_property_result_is_path(func_path: str) -> None:
dirs = platformdirs.PlatformDirs("MyApp", "MyCompany", version="1.0")
result = getattr(dirs, func_path)
assert isinstance(result, Path)


def test_function_interface_is_in_sync(func: str) -> None:
function_dir = getattr(platformdirs, func)
function_path = getattr(platformdirs, func.replace("_dir", "_path"))
assert inspect.isfunction(function_dir)
assert inspect.isfunction(function_path)
function_dir_signature = inspect.Signature.from_callable(function_dir)
function_path_signature = inspect.Signature.from_callable(function_path)
assert function_dir_signature.parameters == function_path_signature.parameters


@pytest.mark.parametrize("root", ["A", "/system", None])
@pytest.mark.parametrize("data", ["D", "/data", None])
def test_android_active(monkeypatch: MonkeyPatch, root: Optional[str], data: Optional[str]) -> None:
Expand Down
2 changes: 2 additions & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ highbit
HKEY
impl
intersphinx
isfunction
jnius
kernel32
lru
Expand All @@ -23,6 +24,7 @@ normpath
ord
param
params
pathlib
pathsep
platformdirs
pyjnius
Expand Down

0 comments on commit df07a00

Please sign in to comment.