Skip to content

Commit 7f47751

Browse files
Support for Termux subsystem (#63)
1 parent 36927be commit 7f47751

File tree

5 files changed

+30
-14
lines changed

5 files changed

+30
-14
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
platformdirs Changelog
22
======================
33

4+
platformdirs 2.5.0
5+
------------------
6+
- Add support for Termux subsystems
7+
48
platformdirs 2.4.1
59
------------------
610
- Drop python 3.6 support

src/platformdirs/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@
1818

1919

2020
def _set_platform_dir_class() -> type[PlatformDirsABC]:
21-
if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
22-
module, name = "platformdirs.android", "Android"
23-
elif sys.platform == "win32":
21+
if sys.platform == "win32":
2422
module, name = "platformdirs.windows", "Windows"
2523
elif sys.platform == "darwin":
2624
module, name = "platformdirs.macos", "MacOS"
2725
else:
2826
module, name = "platformdirs.unix", "Unix"
27+
28+
if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
29+
from platformdirs.android import _android_folder
30+
31+
if _android_folder() is not None:
32+
module, name = "platformdirs.android", "Android"
33+
2934
result: type[PlatformDirsABC] = getattr(importlib.import_module(module), name)
3035
return result
3136

src/platformdirs/android.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import re
55
import sys
66
from functools import lru_cache
7+
from typing import cast
78

89
from .api import PlatformDirsABC
910

@@ -18,7 +19,7 @@ class Android(PlatformDirsABC):
1819
@property
1920
def user_data_dir(self) -> str:
2021
""":return: data directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/files/<AppName>``"""
21-
return self._append_app_name_and_version(_android_folder(), "files")
22+
return self._append_app_name_and_version(cast(str, _android_folder()), "files")
2223

2324
@property
2425
def site_data_dir(self) -> str:
@@ -30,7 +31,7 @@ def user_config_dir(self) -> str:
3031
"""
3132
:return: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
3233
"""
33-
return self._append_app_name_and_version(_android_folder(), "shared_prefs")
34+
return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
3435

3536
@property
3637
def site_config_dir(self) -> str:
@@ -40,7 +41,7 @@ def site_config_dir(self) -> str:
4041
@property
4142
def user_cache_dir(self) -> str:
4243
""":return: cache directory tied to the user, e.g. e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>``"""
43-
return self._append_app_name_and_version(_android_folder(), "cache")
44+
return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
4445

4546
@property
4647
def user_state_dir(self) -> str:
@@ -78,14 +79,14 @@ def user_runtime_dir(self) -> str:
7879

7980

8081
@lru_cache(maxsize=1)
81-
def _android_folder() -> str:
82-
""":return: base folder for the Android OS"""
82+
def _android_folder() -> str | None:
83+
""":return: base folder for the Android OS or None if cannot be found"""
8384
try:
8485
# First try to get path to android app via pyjnius
8586
from jnius import autoclass
8687

8788
Context = autoclass("android.content.Context") # noqa: N806
88-
result: str = Context.getFilesDir().getParentFile().getAbsolutePath()
89+
result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath()
8990
except Exception:
9091
# if fails find an android folder looking path on the sys.path
9192
pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
@@ -94,7 +95,7 @@ def _android_folder() -> str:
9495
result = path.split("/files")[0]
9596
break
9697
else:
97-
raise OSError("Cannot find path to android app folder")
98+
result = None
9899
return result
99100

100101

tests/test_android.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,4 @@ def test_android_folder_not_found(mocker: MockerFixture, monkeypatch: MonkeyPatc
110110

111111
_android_folder.cache_clear()
112112
monkeypatch.setattr(sys, "path", [])
113-
with pytest.raises(OSError, match="Cannot find path to android app folder"):
114-
_android_folder()
113+
assert _android_folder() is None

tests/test_api.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import inspect
4+
import sys
45
from pathlib import Path
56

67
import pytest
@@ -51,14 +52,20 @@ def test_function_interface_is_in_sync(func: str) -> None:
5152

5253
@pytest.mark.parametrize("root", ["A", "/system", None])
5354
@pytest.mark.parametrize("data", ["D", "/data", None])
54-
def test_android_active(monkeypatch: MonkeyPatch, root: str | None, data: str | None) -> None:
55+
@pytest.mark.parametrize("path", ["/data/data/a/files", "/C"])
56+
def test_android_active(monkeypatch: MonkeyPatch, root: str | None, data: str | None, path: str) -> None:
5557
for env_var, value in {"ANDROID_DATA": data, "ANDROID_ROOT": root}.items():
5658
if value is None:
5759
monkeypatch.delenv(env_var, raising=False)
5860
else:
5961
monkeypatch.setenv(env_var, value)
6062

61-
expected = root == "/system" and data == "/data"
63+
from platformdirs.android import _android_folder
64+
65+
_android_folder.cache_clear()
66+
monkeypatch.setattr(sys, "path", ["/A", "/B", path])
67+
68+
expected = root == "/system" and data == "/data" and _android_folder() is not None
6269
if expected:
6370
assert platformdirs._set_platform_dir_class() is Android
6471
else:

0 commit comments

Comments
 (0)