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