| from __future__ import annotations |
| |
| import sys |
| from typing import TYPE_CHECKING, Any |
| from unittest.mock import MagicMock |
| |
| import pytest |
| |
| from platformdirs.android import Android |
| |
| if TYPE_CHECKING: |
| from pytest_mock import MockerFixture |
| |
| |
| @pytest.mark.parametrize( |
| "params", |
| [ |
| {}, |
| {"appname": "foo"}, |
| {"appname": "foo", "appauthor": "bar"}, |
| {"appname": "foo", "appauthor": "bar", "version": "v1.0"}, |
| {"appname": "foo", "appauthor": "bar", "version": "v1.0", "opinion": False}, |
| ], |
| ids=[ |
| "no_args", |
| "app_name", |
| "app_name_with_app_author", |
| "app_name_author_version", |
| "app_name_author_version_false_opinion", |
| ], |
| ) |
| def test_android(mocker: MockerFixture, params: dict[str, Any], func: str) -> None: |
| mocker.patch("platformdirs.android._android_folder", return_value="/data/data/com.example", autospec=True) |
| mocker.patch("platformdirs.android.os.path.join", lambda *args: "/".join(args)) |
| result = getattr(Android(**params), func) |
| |
| suffix_elements = [] |
| if "appname" in params: |
| suffix_elements.append(params["appname"]) |
| if "version" in params: |
| suffix_elements.append(params["version"]) |
| if suffix_elements: |
| suffix_elements.insert(0, "") |
| suffix = "/".join(suffix_elements) |
| |
| val = "/tmp" # noqa: S108 |
| expected_map = { |
| "user_data_dir": f"/data/data/com.example/files{suffix}", |
| "site_data_dir": f"/data/data/com.example/files{suffix}", |
| "user_config_dir": f"/data/data/com.example/shared_prefs{suffix}", |
| "site_config_dir": f"/data/data/com.example/shared_prefs{suffix}", |
| "user_cache_dir": f"/data/data/com.example/cache{suffix}", |
| "site_cache_dir": f"/data/data/com.example/cache{suffix}", |
| "user_state_dir": f"/data/data/com.example/files{suffix}", |
| "user_log_dir": f"/data/data/com.example/cache{suffix}{'' if params.get('opinion', True) is False else '/log'}", |
| "user_documents_dir": "/storage/emulated/0/Documents", |
| "user_downloads_dir": "/storage/emulated/0/Downloads", |
| "user_pictures_dir": "/storage/emulated/0/Pictures", |
| "user_videos_dir": "/storage/emulated/0/DCIM/Camera", |
| "user_music_dir": "/storage/emulated/0/Music", |
| "user_desktop_dir": "/storage/emulated/0/Desktop", |
| "user_runtime_dir": f"/data/data/com.example/cache{suffix}{'' if not params.get('opinion', True) else val}", |
| "site_runtime_dir": f"/data/data/com.example/cache{suffix}{'' if not params.get('opinion', True) else val}", |
| } |
| expected = expected_map[func] |
| |
| assert result == expected |
| |
| |
| def test_android_folder_from_jnius(mocker: MockerFixture) -> None: |
| from platformdirs import PlatformDirs # noqa: PLC0415 |
| from platformdirs.android import _android_folder # noqa: PLC0415 |
| |
| _android_folder.cache_clear() |
| |
| if PlatformDirs is Android: |
| import jnius # pragma: no cover # noqa: PLC0415 |
| |
| autoclass = mocker.spy(jnius, "autoclass") # pragma: no cover |
| else: |
| parent = MagicMock(return_value=MagicMock(getAbsolutePath=MagicMock(return_value="/A"))) # pragma: no cover |
| context = MagicMock(getFilesDir=MagicMock(return_value=MagicMock(getParentFile=parent))) # pragma: no cover |
| autoclass = MagicMock(return_value=context) # pragma: no cover |
| mocker.patch.dict(sys.modules, {"jnius": MagicMock(autoclass=autoclass)}) # pragma: no cover |
| |
| result = _android_folder() |
| assert result == "/A" |
| assert autoclass.call_count == 1 |
| |
| assert autoclass.call_args[0] == ("android.content.Context",) |
| |
| assert _android_folder() is result |
| assert autoclass.call_count == 1 |
| |
| |
| @pytest.mark.parametrize( |
| "path", |
| [ |
| "/data/user/1/a/files", |
| "/data/data/a/files", |
| ], |
| ) |
| def test_android_folder_from_sys_path(mocker: MockerFixture, path: str, monkeypatch: pytest.MonkeyPatch) -> None: |
| mocker.patch.dict(sys.modules, {"jnius": MagicMock(autoclass=MagicMock(side_effect=ModuleNotFoundError))}) |
| |
| from platformdirs.android import _android_folder # noqa: PLC0415 |
| |
| _android_folder.cache_clear() |
| monkeypatch.setattr(sys, "path", ["/A", "/B", path]) |
| |
| result = _android_folder() |
| assert result == path[: -len("/files")] |
| |
| |
| def test_android_folder_not_found(mocker: MockerFixture, monkeypatch: pytest.MonkeyPatch) -> None: |
| mocker.patch.dict(sys.modules, {"jnius": MagicMock(autoclass=MagicMock(side_effect=ModuleNotFoundError))}) |
| |
| from platformdirs.android import _android_folder # noqa: PLC0415 |
| |
| _android_folder.cache_clear() |
| monkeypatch.setattr(sys, "path", []) |
| assert _android_folder() is None |