1"""Stuff that differs in different Python versions and platform
2distributions."""
3
4import importlib.resources
5import locale
6import logging
7import os
8import sys
9from typing import IO
10
11__all__ = ["get_locale_encoding", "get_path_uid", "tomllib", "WINDOWS"]
12
13
14logger = logging.getLogger(__name__)
15
16
17def has_tls() -> bool:
18 try:
19 import _ssl # noqa: F401 # ignore unused
20
21 return True
22 except ImportError:
23 pass
24
25 from pip._vendor.urllib3.util import IS_PYOPENSSL
26
27 return IS_PYOPENSSL
28
29
30def get_locale_encoding() -> str:
31 """Return the locale encoding.
32
33 Uses ``locale.getencoding()`` when available (Python 3.11+) to avoid the
34 ``EncodingWarning`` that ``locale.getpreferredencoding(False)`` raises
35 under UTF-8 Mode.
36 """
37 # TODO: Remove the 3.10 fallback once pip drops Python 3.10 support.
38 if sys.version_info >= (3, 11):
39 return locale.getencoding()
40 return locale.getpreferredencoding(False)
41
42
43def get_path_uid(path: str) -> int:
44 """
45 Return path's uid.
46
47 Does not follow symlinks:
48 https://github.com/pypa/pip/pull/935#discussion_r5307003
49
50 Placed this function in compat due to differences on AIX and
51 Jython, that should eventually go away.
52
53 :raises OSError: When path is a symlink or can't be read.
54 """
55 if hasattr(os, "O_NOFOLLOW"):
56 fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
57 file_uid = os.fstat(fd).st_uid
58 os.close(fd)
59 else: # AIX and Jython
60 # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW
61 if not os.path.islink(path):
62 # older versions of Jython don't have `os.fstat`
63 file_uid = os.stat(path).st_uid
64 else:
65 # raise OSError for parity with os.O_NOFOLLOW above
66 raise OSError(f"{path} is a symlink; Will not return uid for symlinks")
67 return file_uid
68
69
70# The importlib.resources.open_text function was deprecated in 3.11 with suggested
71# replacement we use below.
72if sys.version_info < (3, 11):
73 open_text_resource = importlib.resources.open_text
74else:
75
76 def open_text_resource(
77 package: str, resource: str, encoding: str = "utf-8", errors: str = "strict"
78 ) -> IO[str]:
79 return (importlib.resources.files(package) / resource).open(
80 "r", encoding=encoding, errors=errors
81 )
82
83
84if sys.version_info >= (3, 11):
85 import tomllib
86else:
87 from pip._vendor import tomli as tomllib
88
89
90# windows detection, covers cpython and ironpython
91WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")