blob: a868e29826e1a147193c5c692dd46168755343e4 [file] [log] [blame]
from __future__ import annotations
import builtins
import functools
import inspect
import sys
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable
import pytest
import platformdirs
from platformdirs.android import Android
builtin_import = builtins.__import__
if TYPE_CHECKING:
from types import ModuleType
def test_package_metadata() -> None:
assert hasattr(platformdirs, "__version__")
assert hasattr(platformdirs, "__version_info__")
def test_method_result_is_str(func: str) -> None:
method = getattr(platformdirs, func)
result = method()
assert isinstance(result, str)
def test_property_result_is_str(func: str) -> None:
dirs = platformdirs.PlatformDirs("MyApp", "MyCompany", version="1.0")
result = getattr(dirs, func)
assert isinstance(result, str)
def test_method_result_is_path(func_path: str) -> None:
method = getattr(platformdirs, func_path)
result = method()
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])
@pytest.mark.parametrize("path", ["/data/data/a/files", "/C"])
@pytest.mark.parametrize("shell", ["/data/data/com.app/files/usr/bin/sh", "/usr/bin/sh", None])
@pytest.mark.parametrize("prefix", ["/data/data/com.termux/files/usr", None])
def test_android_active( # noqa: PLR0913
monkeypatch: pytest.MonkeyPatch,
root: str | None,
data: str | None,
path: str,
shell: str | None,
prefix: str | None,
) -> None:
for env_var, value in {"ANDROID_DATA": data, "ANDROID_ROOT": root, "SHELL": shell, "PREFIX": prefix}.items():
if value is None:
monkeypatch.delenv(env_var, raising=False)
else:
monkeypatch.setenv(env_var, value)
from platformdirs.android import _android_folder # noqa: PLC0415
_android_folder.cache_clear()
monkeypatch.setattr(sys, "path", ["/A", "/B", path])
expected = (
root == "/system" and data == "/data" and shell is None and prefix is None and _android_folder() is not None
)
if expected:
assert platformdirs._set_platform_dir_class() is Android # noqa: SLF001
else:
assert platformdirs._set_platform_dir_class() is not Android # noqa: SLF001
def _fake_import(name: str, *args: Any, **kwargs: Any) -> ModuleType: # noqa: ANN401
if name == "ctypes":
msg = f"No module named {name}"
raise ModuleNotFoundError(msg)
return builtin_import(name, *args, **kwargs)
def mock_import(func: Callable[[], None]) -> Callable[[], None]:
@functools.wraps(func)
def wrap() -> None:
platformdirs_module_items = [item for item in sys.modules.items() if item[0].startswith("platformdirs")]
try:
builtins.__import__ = _fake_import
for name, _ in platformdirs_module_items:
del sys.modules[name]
return func()
finally:
# restore original modules
builtins.__import__ = builtin_import
for name, module in platformdirs_module_items:
sys.modules[name] = module
return wrap
@mock_import
def test_no_ctypes() -> None:
import platformdirs # noqa: PLC0415
assert platformdirs