File: test_api.py

package info (click to toggle)
platformdirs 4.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 260 kB
  • sloc: python: 1,702; sh: 7; makefile: 4
file content (132 lines) | stat: -rw-r--r-- 4,360 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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


def test_mypy_subclassing() -> None:
    # Ensure that PlatformDirs / AppDirs is seen as a valid superclass by mypy
    # This is a static type-checking test to ensure we work around
    # the following mypy issue: https://github.com/python/mypy/issues/10962
    class PlatformDirsSubclass(platformdirs.PlatformDirs): ...

    class AppDirsSubclass(platformdirs.AppDirs): ...