platformdirs 4.13.0__tar.gz → 4.13.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {platformdirs-4.13.0 → platformdirs-4.13.2}/PKG-INFO +1 -1
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/_xdg.py +2 -1
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/unix.py +1 -1
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/version.py +2 -2
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/windows.py +5 -3
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_unix.py +36 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_windows.py +23 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/.gitignore +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/LICENSE +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/README.md +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/pyproject.toml +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/__init__.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/__main__.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/android.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/api.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/ios.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/macos.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/py.typed +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/pytest_plugin.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/src/platformdirs/testing.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/conftest.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_android.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_api.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_comp_with_appdirs.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_ios.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_macos.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_main.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_pytest_plugin.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tests/test_testing.py +0 -0
- {platformdirs-4.13.0 → platformdirs-4.13.2}/tox.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: platformdirs
|
|
3
|
-
Version: 4.13.
|
|
3
|
+
Version: 4.13.2
|
|
4
4
|
Summary: A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`.
|
|
5
5
|
Project-URL: Changelog, https://platformdirs.readthedocs.io/en/latest/changelog.html
|
|
6
6
|
Project-URL: Documentation, https://platformdirs.readthedocs.io
|
|
@@ -132,7 +132,8 @@ class XDGMixin(PlatformDirsABC):
|
|
|
132
132
|
def user_fonts_dir(self) -> str:
|
|
133
133
|
"""Fonts directory tied to the user, from ``$XDG_DATA_HOME/fonts`` if set, else platform default."""
|
|
134
134
|
if path := _xdg_dir("XDG_DATA_HOME"):
|
|
135
|
-
|
|
135
|
+
# posixpath keeps the XDG separator even when this mixin runs on a non-POSIX host.
|
|
136
|
+
return posixpath.join(path, "fonts")
|
|
136
137
|
return super().user_fonts_dir
|
|
137
138
|
|
|
138
139
|
@property
|
|
@@ -354,7 +354,7 @@ def _resolve_user_dirs_value(entry: re.Match[str]) -> str | None:
|
|
|
354
354
|
return None
|
|
355
355
|
if entry["quoted"] is not None:
|
|
356
356
|
# xdg-user-dirs-update backslash-escapes $, `, " and \ inside the quotes.
|
|
357
|
-
value = re.sub(r"\\
|
|
357
|
+
value = re.sub(r'\\([$`"\\])', r"\1", value)
|
|
358
358
|
return prefix + value
|
|
359
359
|
|
|
360
360
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '4.13.
|
|
22
|
-
__version_tuple__ = version_tuple = (4, 13,
|
|
21
|
+
__version__ = version = '4.13.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (4, 13, 2)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -355,9 +355,11 @@ def _build_get_win_folder_via_ctypes() -> Callable[[str], str]:
|
|
|
355
355
|
ole32.CLSIDFromString(folder_guid, byref(guid))
|
|
356
356
|
|
|
357
357
|
path_ptr = wintypes.LPWSTR()
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
358
|
+
try:
|
|
359
|
+
shell32.SHGetKnownFolderPath(byref(guid), _KF_FLAG_DONT_VERIFY, None, byref(path_ptr))
|
|
360
|
+
result = path_ptr.value
|
|
361
|
+
finally:
|
|
362
|
+
ole32.CoTaskMemFree(path_ptr)
|
|
361
363
|
|
|
362
364
|
if result is None:
|
|
363
365
|
msg = f"SHGetKnownFolderPath returned NULL for {csidl_name}"
|
|
@@ -701,6 +701,19 @@ def test_without_home_absolute_xdg_dir_applies(
|
|
|
701
701
|
assert getattr(dirs_class(appname="app"), prop) == f"/xdg{suffix}"
|
|
702
702
|
|
|
703
703
|
|
|
704
|
+
@pytest.mark.usefixtures("_clear_xdg_env")
|
|
705
|
+
@pytest.mark.parametrize("dirs_class", _CLASSES)
|
|
706
|
+
@pytest.mark.parametrize(
|
|
707
|
+
("data_home", "expected"),
|
|
708
|
+
[pytest.param("/", "/fonts", id="root"), pytest.param("/xdg/", "/xdg/fonts", id="trailing_slash")],
|
|
709
|
+
)
|
|
710
|
+
def test_user_fonts_dir_xdg_trailing_separator(
|
|
711
|
+
monkeypatch: pytest.MonkeyPatch, dirs_class: type[Unix | MacOS], data_home: str, expected: str
|
|
712
|
+
) -> None:
|
|
713
|
+
monkeypatch.setenv("XDG_DATA_HOME", data_home)
|
|
714
|
+
assert dirs_class().user_fonts_dir == expected
|
|
715
|
+
|
|
716
|
+
|
|
704
717
|
@pytest.mark.usefixtures("_clear_xdg_env", "_unknown_home")
|
|
705
718
|
def test_without_home_absolute_user_dirs_entry_applies(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
|
706
719
|
(tmp_path / "user-dirs.dirs").write_text('XDG_DOCUMENTS_DIR="/srv/docs"\n', encoding="utf-8")
|
|
@@ -1282,6 +1295,29 @@ def test_user_dirs_preserves_percent_signs(folder: str, base: str, tmp_path: Pat
|
|
|
1282
1295
|
assert Unix().user_documents_path == Path(tmp_path if base == "$HOME" else base) / folder
|
|
1283
1296
|
|
|
1284
1297
|
|
|
1298
|
+
@pytest.mark.parametrize(
|
|
1299
|
+
("folder", "expected"),
|
|
1300
|
+
[
|
|
1301
|
+
pytest.param(r"a\q", r"a\q", id="ordinary-letter"),
|
|
1302
|
+
pytest.param(r"a\ b", r"a\ b", id="space"),
|
|
1303
|
+
pytest.param(r"a\-b", r"a\-b", id="hyphen"),
|
|
1304
|
+
pytest.param(r"a\nb", r"a\nb", id="literal-backslash-n"),
|
|
1305
|
+
pytest.param(r"a\'b", r"a\'b", id="single-quote"),
|
|
1306
|
+
pytest.param(r"a\\b", r"a\b", id="escaped-backslash"),
|
|
1307
|
+
pytest.param(r"a\$b", "a$b", id="escaped-dollar"),
|
|
1308
|
+
pytest.param(r"a\`b", "a`b", id="escaped-backtick"),
|
|
1309
|
+
pytest.param(r"a\"b", 'a"b', id="escaped-double-quote"),
|
|
1310
|
+
pytest.param(r"a\q\\b\$c", r"a\q\b$c", id="mixed-escapes"),
|
|
1311
|
+
],
|
|
1312
|
+
)
|
|
1313
|
+
@pytest.mark.parametrize("base", ["$HOME", "/absolute"])
|
|
1314
|
+
def test_user_dirs_double_quoted_backslashes(
|
|
1315
|
+
folder: str, expected: str, base: str, tmp_path: Path, user_dirs_file: Path
|
|
1316
|
+
) -> None:
|
|
1317
|
+
user_dirs_file.write_text(f'XDG_DOCUMENTS_DIR="{base}/{folder}"\n', encoding="utf-8")
|
|
1318
|
+
assert Unix().user_documents_path == Path(tmp_path if base == "$HOME" else base) / expected
|
|
1319
|
+
|
|
1320
|
+
|
|
1285
1321
|
@pytest.mark.parametrize(
|
|
1286
1322
|
("content", "expected"),
|
|
1287
1323
|
[
|
|
@@ -483,6 +483,29 @@ def test_get_win_folder_via_ctypes_null_result(mocker: MockerFixture) -> None:
|
|
|
483
483
|
_cleanup_ctypes_mocks()
|
|
484
484
|
|
|
485
485
|
|
|
486
|
+
@pytest.mark.parametrize(
|
|
487
|
+
"path",
|
|
488
|
+
[pytest.param(None, id="null"), pytest.param(r"C:\Users\Test\AppData\Local", id="populated")],
|
|
489
|
+
)
|
|
490
|
+
def test_get_win_folder_via_ctypes_frees_path_on_error(mocker: MockerFixture, path: str | None) -> None:
|
|
491
|
+
_setup_ctypes_mocks(mocker)
|
|
492
|
+
error = OSError("SHGetKnownFolderPath failed")
|
|
493
|
+
dlls = {"ole32": MagicMock(), "shell32": MagicMock(SHGetKnownFolderPath=MagicMock(side_effect=error))}
|
|
494
|
+
mocker.patch.object(ctypes, "WinDLL", MagicMock(side_effect=dlls.__getitem__))
|
|
495
|
+
mocker.patch("ctypes.byref", side_effect=lambda x: x)
|
|
496
|
+
path_ptr = MagicMock(value=path)
|
|
497
|
+
mocker.patch("ctypes.wintypes.LPWSTR", return_value=path_ptr)
|
|
498
|
+
|
|
499
|
+
try:
|
|
500
|
+
importlib.reload(windows)
|
|
501
|
+
with pytest.raises(OSError, match=r"^SHGetKnownFolderPath failed$"):
|
|
502
|
+
windows.get_win_folder_via_ctypes("CSIDL_LOCAL_APPDATA")
|
|
503
|
+
finally:
|
|
504
|
+
_cleanup_ctypes_mocks()
|
|
505
|
+
|
|
506
|
+
dlls["ole32"].CoTaskMemFree.assert_called_once_with(path_ptr)
|
|
507
|
+
|
|
508
|
+
|
|
486
509
|
def _short_name(_long: str, buf: ctypes.Array[ctypes.c_wchar], _size: int) -> int:
|
|
487
510
|
buf.value = r"C:\Users\UKASZ~1\AppData\Local"
|
|
488
511
|
return len(buf.value)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|