Skip to content

Commit 674d8cf

Browse files
committed
Upgrade platformdirs to 2.4.0
1 parent e1dd4b4 commit 674d8cf

File tree

10 files changed

+198
-10
lines changed

10 files changed

+198
-10
lines changed

news/platformdirs.vendor.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Patch platformdirs import its submodules from ``pip._vendor.platformdirs``.
1+
Upgrade platformdirs to 2.4.0

src/pip/_vendor/platformdirs/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ def user_log_dir(
144144
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_dir
145145

146146

147+
def user_documents_dir() -> str:
148+
"""
149+
:returns: documents directory tied to the user
150+
"""
151+
return PlatformDirs().user_documents_dir
152+
153+
154+
def user_runtime_dir(
155+
appname: Optional[str] = None,
156+
appauthor: Union[str, None, "Literal[False]"] = None,
157+
version: Optional[str] = None,
158+
opinion: bool = True,
159+
) -> str:
160+
"""
161+
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
162+
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
163+
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
164+
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
165+
:returns: runtime directory tied to the user
166+
"""
167+
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_dir
168+
169+
147170
def user_data_path(
148171
appname: Optional[str] = None,
149172
appauthor: Union[str, None, "Literal[False]"] = None,
@@ -256,6 +279,29 @@ def user_log_path(
256279
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_path
257280

258281

282+
def user_documents_path() -> Path:
283+
"""
284+
:returns: documents path tied to the user
285+
"""
286+
return PlatformDirs().user_documents_path
287+
288+
289+
def user_runtime_path(
290+
appname: Optional[str] = None,
291+
appauthor: Union[str, None, "Literal[False]"] = None,
292+
version: Optional[str] = None,
293+
opinion: bool = True,
294+
) -> Path:
295+
"""
296+
:param appname: See `appname <platformdirs.api.PlatformDirsABC.appname>`.
297+
:param appauthor: See `appauthor <platformdirs.api.PlatformDirsABC.appauthor>`.
298+
:param version: See `version <platformdirs.api.PlatformDirsABC.version>`.
299+
:param opinion: See `opinion <platformdirs.api.PlatformDirsABC.opinion>`.
300+
:returns: runtime path tied to the user
301+
"""
302+
return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_path
303+
304+
259305
__all__ = [
260306
"__version__",
261307
"__version_info__",
@@ -267,13 +313,17 @@ def user_log_path(
267313
"user_cache_dir",
268314
"user_state_dir",
269315
"user_log_dir",
316+
"user_documents_dir",
317+
"user_runtime_dir",
270318
"site_data_dir",
271319
"site_config_dir",
272320
"user_data_path",
273321
"user_config_path",
274322
"user_cache_path",
275323
"user_state_path",
276324
"user_log_path",
325+
"user_documents_path",
326+
"user_runtime_path",
277327
"site_data_path",
278328
"site_config_path",
279329
]

src/pip/_vendor/platformdirs/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"user_cache_dir",
77
"user_state_dir",
88
"user_log_dir",
9+
"user_documents_dir",
10+
"user_runtime_dir",
911
"site_data_dir",
1012
"site_config_dir",
1113
)

src/pip/_vendor/platformdirs/android.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ def user_log_dir(self) -> str:
5656
path = os.path.join(path, "log")
5757
return path
5858

59+
@property
60+
def user_documents_dir(self) -> str:
61+
"""
62+
:return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``
63+
"""
64+
return _android_documents_folder()
65+
66+
@property
67+
def user_runtime_dir(self) -> str:
68+
"""
69+
:return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
70+
e.g. ``/data/user/<userid>/<packagename>/cache/<AppName>/tmp``
71+
"""
72+
path = self.user_cache_dir
73+
if self.opinion:
74+
path = os.path.join(path, "tmp")
75+
return path
76+
5977

6078
@lru_cache(maxsize=1)
6179
def _android_folder() -> str:
@@ -78,6 +96,22 @@ def _android_folder() -> str:
7896
return result
7997

8098

99+
@lru_cache(maxsize=1)
100+
def _android_documents_folder() -> str:
101+
""":return: documents folder for the Android OS"""
102+
# Get directories with pyjnius
103+
try:
104+
from jnius import autoclass # noqa: SC200
105+
106+
Context = autoclass("android.content.Context") # noqa: SC200
107+
Environment = autoclass("android.os.Environment")
108+
documents_dir: str = Context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
109+
except Exception:
110+
documents_dir = "/storage/emulated/0/Documents"
111+
112+
return documents_dir
113+
114+
81115
__all__ = [
82116
"Android",
83117
]

src/pip/_vendor/platformdirs/api.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ def user_state_dir(self) -> str:
9999
def user_log_dir(self) -> str:
100100
""":return: log directory tied to the user"""
101101

102+
@property
103+
@abstractmethod
104+
def user_documents_dir(self) -> str:
105+
""":return: documents directory tied to the user"""
106+
107+
@property
108+
@abstractmethod
109+
def user_runtime_dir(self) -> str:
110+
""":return: runtime directory tied to the user"""
111+
102112
@property
103113
def user_data_path(self) -> Path:
104114
""":return: data path tied to the user"""
@@ -133,3 +143,13 @@ def user_state_path(self) -> Path:
133143
def user_log_path(self) -> Path:
134144
""":return: log path tied to the user"""
135145
return Path(self.user_log_dir)
146+
147+
@property
148+
def user_documents_path(self) -> Path:
149+
""":return: documents path tied to the user"""
150+
return Path(self.user_documents_dir)
151+
152+
@property
153+
def user_runtime_path(self) -> Path:
154+
""":return: runtime path tied to the user"""
155+
return Path(self.user_runtime_dir)

src/pip/_vendor/platformdirs/macos.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ def user_log_dir(self) -> str:
4646
""":return: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``"""
4747
return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs"))
4848

49+
@property
50+
def user_documents_dir(self) -> str:
51+
""":return: documents directory tied to the user, e.g. ``~/Documents``"""
52+
return os.path.expanduser("~/Documents")
53+
54+
@property
55+
def user_runtime_dir(self) -> str:
56+
""":return: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``"""
57+
return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems"))
58+
4959

5060
__all__ = [
5161
"MacOS",

src/pip/_vendor/platformdirs/unix.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
import os
2+
import sys
3+
from configparser import ConfigParser
24
from pathlib import Path
5+
from typing import Optional
36

47
from .api import PlatformDirsABC
58

9+
if sys.platform.startswith("linux"): # pragma: no branch # no op check, only to please the type checker
10+
from os import getuid
11+
else:
12+
13+
def getuid() -> int:
14+
raise RuntimeError("should only be used on Linux")
15+
616

717
class Unix(PlatformDirsABC):
818
"""
@@ -103,6 +113,30 @@ def user_log_dir(self) -> str:
103113
path = os.path.join(path, "log")
104114
return path
105115

116+
@property
117+
def user_documents_dir(self) -> str:
118+
"""
119+
:return: documents directory tied to the user, e.g. ``~/Documents``
120+
"""
121+
documents_dir = _get_user_dirs_folder("XDG_DOCUMENTS_DIR")
122+
if documents_dir is None:
123+
documents_dir = os.environ.get("XDG_DOCUMENTS_DIR", "").strip()
124+
if not documents_dir:
125+
documents_dir = os.path.expanduser("~/Documents")
126+
127+
return documents_dir
128+
129+
@property
130+
def user_runtime_dir(self) -> str:
131+
"""
132+
:return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or
133+
``$XDG_RUNTIME_DIR/$appname/$version``
134+
"""
135+
path = os.environ.get("XDG_RUNTIME_DIR", "")
136+
if not path.strip():
137+
path = f"/run/user/{getuid()}"
138+
return self._append_app_name_and_version(path)
139+
106140
@property
107141
def site_data_path(self) -> Path:
108142
""":return: data path shared by users. Only return first item, even if ``multipath`` is set to ``True``"""
@@ -120,6 +154,27 @@ def _first_item_as_path_if_multipath(self, directory: str) -> Path:
120154
return Path(directory)
121155

122156

157+
def _get_user_dirs_folder(key: str) -> Optional[str]:
158+
"""Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/"""
159+
user_dirs_config_path = os.path.join(Unix().user_config_dir, "user-dirs.dirs")
160+
if os.path.exists(user_dirs_config_path):
161+
parser = ConfigParser()
162+
163+
with open(user_dirs_config_path) as stream:
164+
# Add fake section header, so ConfigParser doesn't complain
165+
parser.read_string(f"[top]\n{stream.read()}")
166+
167+
if key not in parser["top"]:
168+
return None
169+
170+
path = parser["top"][key].strip('"')
171+
# Handle relative home paths
172+
path = path.replace("$HOME", os.path.expanduser("~"))
173+
return path
174+
175+
return None
176+
177+
123178
__all__ = [
124179
"Unix",
125180
]
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
""" Version information """
22

3-
__version__ = "2.2.0"
4-
__version_info__ = (2, 2, 0)
3+
__version__ = "2.4.0"
4+
__version_info__ = (2, 4, 0)

src/pip/_vendor/platformdirs/windows.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,28 @@ def user_log_dir(self) -> str:
8080
path = os.path.join(path, "Logs")
8181
return path
8282

83+
@property
84+
def user_documents_dir(self) -> str:
85+
"""
86+
:return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``
87+
"""
88+
return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
89+
90+
@property
91+
def user_runtime_dir(self) -> str:
92+
"""
93+
:return: runtime directory tied to the user, e.g.
94+
``%USERPROFILE%\\AppData\\Local\\Temp\\$appauthor\\$appname``
95+
"""
96+
path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp"))
97+
return self._append_parts(path)
98+
8399

84100
def get_win_folder_from_env_vars(csidl_name: str) -> str:
85101
"""Get folder from environment variables."""
102+
if csidl_name == "CSIDL_PERSONAL": # does not have an environment name
103+
return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents")
104+
86105
env_var_name = {
87106
"CSIDL_APPDATA": "APPDATA",
88107
"CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
@@ -107,6 +126,7 @@ def get_win_folder_from_registry(csidl_name: str) -> str:
107126
"CSIDL_APPDATA": "AppData",
108127
"CSIDL_COMMON_APPDATA": "Common AppData",
109128
"CSIDL_LOCAL_APPDATA": "Local AppData",
129+
"CSIDL_PERSONAL": "Personal",
110130
}.get(csidl_name)
111131
if shell_folder_name is None:
112132
raise ValueError(f"Unknown CSIDL name: {csidl_name}")
@@ -124,6 +144,7 @@ def get_win_folder_via_ctypes(csidl_name: str) -> str:
124144
"CSIDL_APPDATA": 26,
125145
"CSIDL_COMMON_APPDATA": 35,
126146
"CSIDL_LOCAL_APPDATA": 28,
147+
"CSIDL_PERSONAL": 5,
127148
}.get(csidl_name)
128149
if csidl_const is None:
129150
raise ValueError(f"Unknown CSIDL name: {csidl_name}")
@@ -132,12 +153,8 @@ def get_win_folder_via_ctypes(csidl_name: str) -> str:
132153
windll = getattr(ctypes, "windll") # noqa: B009 # using getattr to avoid false positive with mypy type checker
133154
windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
134155

135-
has_high_char = False # Downgrade to short path name if it has highbit chars.
136-
for c in buf:
137-
if ord(c) > 255:
138-
has_high_char = True
139-
break
140-
if has_high_char:
156+
# Downgrade to short path name if it has highbit chars.
157+
if any(ord(c) > 255 for c in buf):
141158
buf2 = ctypes.create_unicode_buffer(1024)
142159
if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
143160
buf = buf2

src/pip/_vendor/vendor.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ html5lib==1.1
66
msgpack==1.0.2
77
packaging==21.0
88
pep517==0.11.0
9-
platformdirs==2.2.0
9+
platformdirs==2.4.0
1010
progress==1.5
1111
pyparsing==2.4.7
1212
requests==2.26.0

0 commit comments

Comments
 (0)