diff --git a/CHANGES.rst b/CHANGES.rst index 1fb666c..d50cbb9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,10 @@ platformdirs Changelog ====================== +platformdirs 2.5.0 +------------------ +- Add support for Termux subsystems + platformdirs 2.4.1 ------------------ - Drop python 3.6 support diff --git a/src/platformdirs/__init__.py b/src/platformdirs/__init__.py index 46b1157..d66256d 100644 --- a/src/platformdirs/__init__.py +++ b/src/platformdirs/__init__.py @@ -18,14 +18,19 @@ def _set_platform_dir_class() -> type[PlatformDirsABC]: - if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system": - module, name = "platformdirs.android", "Android" - elif sys.platform == "win32": + if sys.platform == "win32": module, name = "platformdirs.windows", "Windows" elif sys.platform == "darwin": module, name = "platformdirs.macos", "MacOS" else: module, name = "platformdirs.unix", "Unix" + + if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system": + from platformdirs.android import _android_folder + + if _android_folder() is not None: + module, name = "platformdirs.android", "Android" + result: type[PlatformDirsABC] = getattr(importlib.import_module(module), name) return result diff --git a/src/platformdirs/android.py b/src/platformdirs/android.py index a684058..eda8093 100644 --- a/src/platformdirs/android.py +++ b/src/platformdirs/android.py @@ -4,6 +4,7 @@ import re import sys from functools import lru_cache +from typing import cast from .api import PlatformDirsABC @@ -18,7 +19,7 @@ class Android(PlatformDirsABC): @property def user_data_dir(self) -> str: """:return: data directory tied to the user, e.g. ``/data/user///files/``""" - return self._append_app_name_and_version(_android_folder(), "files") + return self._append_app_name_and_version(cast(str, _android_folder()), "files") @property def site_data_dir(self) -> str: @@ -30,7 +31,7 @@ def user_config_dir(self) -> str: """ :return: config directory tied to the user, e.g. ``/data/user///shared_prefs/`` """ - return self._append_app_name_and_version(_android_folder(), "shared_prefs") + return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs") @property def site_config_dir(self) -> str: @@ -40,7 +41,7 @@ def site_config_dir(self) -> str: @property def user_cache_dir(self) -> str: """:return: cache directory tied to the user, e.g. e.g. ``/data/user///cache/``""" - return self._append_app_name_and_version(_android_folder(), "cache") + return self._append_app_name_and_version(cast(str, _android_folder()), "cache") @property def user_state_dir(self) -> str: @@ -78,14 +79,14 @@ def user_runtime_dir(self) -> str: @lru_cache(maxsize=1) -def _android_folder() -> str: - """:return: base folder for the Android OS""" +def _android_folder() -> str | None: + """:return: base folder for the Android OS or None if cannot be found""" try: # First try to get path to android app via pyjnius from jnius import autoclass Context = autoclass("android.content.Context") # noqa: N806 - result: str = Context.getFilesDir().getParentFile().getAbsolutePath() + result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath() except Exception: # if fails find an android folder looking path on the sys.path pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files") @@ -94,7 +95,7 @@ def _android_folder() -> str: result = path.split("/files")[0] break else: - raise OSError("Cannot find path to android app folder") + result = None return result diff --git a/tests/test_android.py b/tests/test_android.py index 8f98e69..51dd09b 100644 --- a/tests/test_android.py +++ b/tests/test_android.py @@ -110,5 +110,4 @@ def test_android_folder_not_found(mocker: MockerFixture, monkeypatch: MonkeyPatc _android_folder.cache_clear() monkeypatch.setattr(sys, "path", []) - with pytest.raises(OSError, match="Cannot find path to android app folder"): - _android_folder() + assert _android_folder() is None diff --git a/tests/test_api.py b/tests/test_api.py index 1a4e6a7..96ac24b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,6 +1,7 @@ from __future__ import annotations import inspect +import sys from pathlib import Path import pytest @@ -51,14 +52,20 @@ def test_function_interface_is_in_sync(func: str) -> None: @pytest.mark.parametrize("root", ["A", "/system", None]) @pytest.mark.parametrize("data", ["D", "/data", None]) -def test_android_active(monkeypatch: MonkeyPatch, root: str | None, data: str | None) -> None: +@pytest.mark.parametrize("path", ["/data/data/a/files", "/C"]) +def test_android_active(monkeypatch: MonkeyPatch, root: str | None, data: str | None, path: str) -> None: for env_var, value in {"ANDROID_DATA": data, "ANDROID_ROOT": root}.items(): if value is None: monkeypatch.delenv(env_var, raising=False) else: monkeypatch.setenv(env_var, value) - expected = root == "/system" and data == "/data" + from platformdirs.android import _android_folder + + _android_folder.cache_clear() + monkeypatch.setattr(sys, "path", ["/A", "/B", path]) + + expected = root == "/system" and data == "/data" and _android_folder() is not None if expected: assert platformdirs._set_platform_dir_class() is Android else: