|
1 |
| -import os |
2 | 1 | from pathlib import Path
|
3 |
| -import sys |
4 | 2 | from tempfile import TemporaryDirectory
|
5 |
| -from typing import Callable, Literal, Optional |
| 3 | +from typing import Callable, Optional |
6 | 4 | from typing_extensions import ParamSpec
|
7 | 5 | from weakref import finalize
|
8 | 6 |
|
| 7 | +from nonestorage import user_cache_dir, user_data_dir |
| 8 | + |
9 | 9 | from ..event.config import ConfigReload
|
10 | 10 | from ..plugin.model import RootlessPlugin
|
11 | 11 |
|
12 |
| -WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") |
13 |
| - |
14 |
| - |
15 |
| -def user_cache_dir(appname: str) -> Path: |
16 |
| - r""" |
17 |
| - Return full path to the user-specific cache dir for this application. |
18 |
| - "appname" is the name of application. |
19 |
| - Typical user cache directories are: |
20 |
| - macOS: ~/Library/Caches/<AppName> |
21 |
| - Unix: ~/.cache/<AppName> (XDG default) |
22 |
| - Windows: C:\Users\<username>\AppData\Local\<AppName>\Cache |
23 |
| - On Windows the only suggestion in the MSDN docs is that local settings go |
24 |
| - in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the |
25 |
| - non-roaming app data dir (the default returned by `user_data_dir`). Apps |
26 |
| - typically put cache data somewhere *under* the given dir here. Some |
27 |
| - examples: |
28 |
| - ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache |
29 |
| - ...\Acme\SuperApp\Cache\1.0 |
30 |
| - OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. |
31 |
| - """ |
32 |
| - if WINDOWS: |
33 |
| - return _get_win_folder("CSIDL_LOCAL_APPDATA") / appname / "Cache" |
34 |
| - elif sys.platform == "darwin": |
35 |
| - return Path("~/Library/Caches").expanduser() / appname |
36 |
| - else: |
37 |
| - return Path(os.getenv("XDG_CACHE_HOME", "~/.cache")).expanduser() / appname |
38 |
| - |
39 |
| - |
40 |
| -def user_data_dir(appname: str, roaming: bool = False) -> Path: |
41 |
| - r""" |
42 |
| - Return full path to the user-specific data dir for this application. |
43 |
| - "appname" is the name of application. |
44 |
| - If None, just the system directory is returned. |
45 |
| - "roaming" (boolean, default False) can be set True to use the Windows |
46 |
| - roaming appdata directory. That means that for users on a Windows |
47 |
| - network setup for roaming profiles, this user data will be |
48 |
| - sync'd on login. See |
49 |
| - <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> |
50 |
| - for a discussion of issues. |
51 |
| - Typical user data directories are: |
52 |
| - macOS: ~/Library/Application Support/<AppName> |
53 |
| - Unix: ~/.local/share/<AppName> # or in |
54 |
| - $XDG_DATA_HOME, if defined |
55 |
| - Win XP (not roaming): C:\Documents and Settings\<username>\ ... |
56 |
| - ...Application Data\<AppName> |
57 |
| - Win XP (roaming): C:\Documents and Settings\<username>\Local ... |
58 |
| - ...Settings\Application Data\<AppName> |
59 |
| - Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppName> |
60 |
| - Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppName> |
61 |
| - For Unix, we follow the XDG spec and support $XDG_DATA_HOME. |
62 |
| - That means, by default "~/.local/share/<AppName>". |
63 |
| - """ |
64 |
| - if WINDOWS: |
65 |
| - const = "CSIDL_APPDATA" if roaming else "CSIDL_LOCAL_APPDATA" |
66 |
| - return Path(_get_win_folder(const)) / appname |
67 |
| - elif sys.platform == "darwin": |
68 |
| - return Path("~/Library/Application Support/").expanduser() / appname |
69 |
| - else: |
70 |
| - return Path(os.getenv("XDG_DATA_HOME", "~/.local/share")).expanduser() / appname |
71 |
| - |
72 |
| - |
73 |
| -# -- Windows support functions -- |
74 |
| -def _get_win_folder_from_registry( |
75 |
| - csidl_name: Literal["CSIDL_APPDATA", "CSIDL_COMMON_APPDATA", "CSIDL_LOCAL_APPDATA"] |
76 |
| -) -> Path: |
77 |
| - """ |
78 |
| - This is a fallback technique at best. I'm not sure if using the |
79 |
| - registry for this guarantees us the correct answer for all CSIDL_* |
80 |
| - names. |
81 |
| - """ |
82 |
| - import winreg |
83 |
| - |
84 |
| - shell_folder_name = { |
85 |
| - "CSIDL_APPDATA": "AppData", |
86 |
| - "CSIDL_COMMON_APPDATA": "Common AppData", |
87 |
| - "CSIDL_LOCAL_APPDATA": "Local AppData", |
88 |
| - }[csidl_name] |
89 |
| - |
90 |
| - key = winreg.OpenKey( |
91 |
| - winreg.HKEY_CURRENT_USER, |
92 |
| - r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", |
93 |
| - ) |
94 |
| - directory, _type = winreg.QueryValueEx(key, shell_folder_name) |
95 |
| - return Path(directory) |
96 |
| - |
97 |
| - |
98 |
| -def _get_win_folder_with_ctypes( |
99 |
| - csidl_name: Literal["CSIDL_APPDATA", "CSIDL_COMMON_APPDATA", "CSIDL_LOCAL_APPDATA"] |
100 |
| -) -> Path: |
101 |
| - csidl_const = { |
102 |
| - "CSIDL_APPDATA": 26, |
103 |
| - "CSIDL_COMMON_APPDATA": 35, |
104 |
| - "CSIDL_LOCAL_APPDATA": 28, |
105 |
| - }[csidl_name] |
106 |
| - |
107 |
| - buf = ctypes.create_unicode_buffer(1024) |
108 |
| - ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) |
109 |
| - |
110 |
| - # Downgrade to short path name if have highbit chars. See |
111 |
| - # <http://bugs.activestate.com/show_bug.cgi?id=85099>. |
112 |
| - has_high_char = any(ord(c) > 255 for c in buf) |
113 |
| - if has_high_char: |
114 |
| - buf2 = ctypes.create_unicode_buffer(1024) |
115 |
| - if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): |
116 |
| - buf = buf2 |
117 |
| - |
118 |
| - return Path(buf.value) |
119 |
| - |
120 |
| - |
121 |
| -if WINDOWS: |
122 |
| - try: |
123 |
| - import ctypes |
124 |
| - |
125 |
| - _get_win_folder = _get_win_folder_with_ctypes |
126 |
| - except ImportError: |
127 |
| - _get_win_folder = _get_win_folder_from_registry |
128 |
| - |
129 |
| - |
130 | 12 | P = ParamSpec("P")
|
131 | 13 |
|
132 | 14 |
|
|
0 commit comments