Skip to content

Commit

Permalink
Allow working without ctypes (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowone authored Apr 23, 2024
1 parent 89b6b2b commit b44d57d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/platformdirs/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from __future__ import annotations

import ctypes
import os
import sys
from functools import lru_cache
Expand Down Expand Up @@ -217,6 +216,8 @@ def get_win_folder_via_ctypes(csidl_name: str) -> str:
# Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead.
# https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid

import ctypes # noqa: PLC0415

csidl_const = {
"CSIDL_APPDATA": 26,
"CSIDL_COMMON_APPDATA": 35,
Expand Down Expand Up @@ -249,8 +250,13 @@ def get_win_folder_via_ctypes(csidl_name: str) -> str:


def _pick_get_win_folder() -> Callable[[str], str]:
if hasattr(ctypes, "windll"):
return get_win_folder_via_ctypes
try:
import ctypes # noqa: PLC0415
except ImportError:
pass
else:
if hasattr(ctypes, "windll"):
return get_win_folder_via_ctypes
try:
import winreg # noqa: PLC0415, F401
except ImportError:
Expand Down
40 changes: 40 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
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__")
Expand Down Expand Up @@ -80,3 +89,34 @@ def test_android_active( # noqa: PLR0913
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":
raise ModuleNotFoundError("No module named %s" % name)
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

0 comments on commit b44d57d

Please sign in to comment.