Skip to content

Commit

Permalink
Support for Termux subsystem (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
YariKartoshe4ka committed Feb 9, 2022
1 parent 36927be commit 7f47751
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 14 deletions.
4 changes: 4 additions & 0 deletions 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
Expand Down
11 changes: 8 additions & 3 deletions src/platformdirs/__init__.py
Expand Up @@ -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

Expand Down
15 changes: 8 additions & 7 deletions src/platformdirs/android.py
Expand Up @@ -4,6 +4,7 @@
import re
import sys
from functools import lru_cache
from typing import cast

from .api import PlatformDirsABC

Expand All @@ -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/<userid>/<packagename>/files/<AppName>``"""
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:
Expand All @@ -30,7 +31,7 @@ def user_config_dir(self) -> str:
"""
:return: config directory tied to the user, e.g. ``/data/user/<userid>/<packagename>/shared_prefs/<AppName>``
"""
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:
Expand All @@ -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/<userid>/<packagename>/cache/<AppName>``"""
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:
Expand Down Expand Up @@ -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")
Expand All @@ -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


Expand Down
3 changes: 1 addition & 2 deletions tests/test_android.py
Expand Up @@ -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
11 changes: 9 additions & 2 deletions tests/test_api.py
@@ -1,6 +1,7 @@
from __future__ import annotations

import inspect
import sys
from pathlib import Path

import pytest
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 7f47751

Please sign in to comment.