Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hhhrrrttt222111
GitHub Repository: hhhrrrttt222111/Dorkify
Path: blob/master/venv/Lib/site-packages/pip/_internal/utils/compat.py
811 views
1
"""Stuff that differs in different Python versions and platform
2
distributions."""
3
4
# The following comment should be removed at some point in the future.
5
# mypy: disallow-untyped-defs=False
6
7
from __future__ import absolute_import, division
8
9
import codecs
10
import locale
11
import logging
12
import os
13
import shutil
14
import sys
15
16
from pip._vendor.six import PY2, text_type
17
18
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
19
20
if MYPY_CHECK_RUNNING:
21
from typing import Optional, Text, Tuple, Union
22
23
try:
24
import ipaddress
25
except ImportError:
26
try:
27
from pip._vendor import ipaddress # type: ignore
28
except ImportError:
29
import ipaddr as ipaddress # type: ignore
30
ipaddress.ip_address = ipaddress.IPAddress # type: ignore
31
ipaddress.ip_network = ipaddress.IPNetwork # type: ignore
32
33
34
__all__ = [
35
"ipaddress", "uses_pycache", "console_to_str",
36
"get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size",
37
]
38
39
40
logger = logging.getLogger(__name__)
41
42
if PY2:
43
import imp
44
45
try:
46
cache_from_source = imp.cache_from_source # type: ignore
47
except AttributeError:
48
# does not use __pycache__
49
cache_from_source = None
50
51
uses_pycache = cache_from_source is not None
52
else:
53
uses_pycache = True
54
from importlib.util import cache_from_source
55
56
57
if PY2:
58
# In Python 2.7, backslashreplace exists
59
# but does not support use for decoding.
60
# We implement our own replace handler for this
61
# situation, so that we can consistently use
62
# backslash replacement for all versions.
63
def backslashreplace_decode_fn(err):
64
raw_bytes = (err.object[i] for i in range(err.start, err.end))
65
# Python 2 gave us characters - convert to numeric bytes
66
raw_bytes = (ord(b) for b in raw_bytes)
67
return u"".join(map(u"\\x{:x}".format, raw_bytes)), err.end
68
codecs.register_error(
69
"backslashreplace_decode",
70
backslashreplace_decode_fn,
71
)
72
backslashreplace_decode = "backslashreplace_decode"
73
else:
74
backslashreplace_decode = "backslashreplace"
75
76
77
def has_tls():
78
# type: () -> bool
79
try:
80
import _ssl # noqa: F401 # ignore unused
81
return True
82
except ImportError:
83
pass
84
85
from pip._vendor.urllib3.util import IS_PYOPENSSL
86
return IS_PYOPENSSL
87
88
89
def str_to_display(data, desc=None):
90
# type: (Union[bytes, Text], Optional[str]) -> Text
91
"""
92
For display or logging purposes, convert a bytes object (or text) to
93
text (e.g. unicode in Python 2) safe for output.
94
95
:param desc: An optional phrase describing the input data, for use in
96
the log message if a warning is logged. Defaults to "Bytes object".
97
98
This function should never error out and so can take a best effort
99
approach. It is okay to be lossy if needed since the return value is
100
just for display.
101
102
We assume the data is in the locale preferred encoding. If it won't
103
decode properly, we warn the user but decode as best we can.
104
105
We also ensure that the output can be safely written to standard output
106
without encoding errors.
107
"""
108
if isinstance(data, text_type):
109
return data
110
111
# Otherwise, data is a bytes object (str in Python 2).
112
# First, get the encoding we assume. This is the preferred
113
# encoding for the locale, unless that is not found, or
114
# it is ASCII, in which case assume UTF-8
115
encoding = locale.getpreferredencoding()
116
if (not encoding) or codecs.lookup(encoding).name == "ascii":
117
encoding = "utf-8"
118
119
# Now try to decode the data - if we fail, warn the user and
120
# decode with replacement.
121
try:
122
decoded_data = data.decode(encoding)
123
except UnicodeDecodeError:
124
if desc is None:
125
desc = 'Bytes object'
126
msg_format = '{} does not appear to be encoded as %s'.format(desc)
127
logger.warning(msg_format, encoding)
128
decoded_data = data.decode(encoding, errors=backslashreplace_decode)
129
130
# Make sure we can print the output, by encoding it to the output
131
# encoding with replacement of unencodable characters, and then
132
# decoding again.
133
# We use stderr's encoding because it's less likely to be
134
# redirected and if we don't find an encoding we skip this
135
# step (on the assumption that output is wrapped by something
136
# that won't fail).
137
# The double getattr is to deal with the possibility that we're
138
# being called in a situation where sys.__stderr__ doesn't exist,
139
# or doesn't have an encoding attribute. Neither of these cases
140
# should occur in normal pip use, but there's no harm in checking
141
# in case people use pip in (unsupported) unusual situations.
142
output_encoding = getattr(getattr(sys, "__stderr__", None),
143
"encoding", None)
144
145
if output_encoding:
146
output_encoded = decoded_data.encode(
147
output_encoding,
148
errors="backslashreplace"
149
)
150
decoded_data = output_encoded.decode(output_encoding)
151
152
return decoded_data
153
154
155
def console_to_str(data):
156
# type: (bytes) -> Text
157
"""Return a string, safe for output, of subprocess output.
158
"""
159
return str_to_display(data, desc='Subprocess output')
160
161
162
def get_path_uid(path):
163
# type: (str) -> int
164
"""
165
Return path's uid.
166
167
Does not follow symlinks:
168
https://github.com/pypa/pip/pull/935#discussion_r5307003
169
170
Placed this function in compat due to differences on AIX and
171
Jython, that should eventually go away.
172
173
:raises OSError: When path is a symlink or can't be read.
174
"""
175
if hasattr(os, 'O_NOFOLLOW'):
176
fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
177
file_uid = os.fstat(fd).st_uid
178
os.close(fd)
179
else: # AIX and Jython
180
# WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW
181
if not os.path.islink(path):
182
# older versions of Jython don't have `os.fstat`
183
file_uid = os.stat(path).st_uid
184
else:
185
# raise OSError for parity with os.O_NOFOLLOW above
186
raise OSError(
187
"{} is a symlink; Will not return uid for symlinks".format(
188
path)
189
)
190
return file_uid
191
192
193
def expanduser(path):
194
# type: (str) -> str
195
"""
196
Expand ~ and ~user constructions.
197
198
Includes a workaround for https://bugs.python.org/issue14768
199
"""
200
expanded = os.path.expanduser(path)
201
if path.startswith('~/') and expanded.startswith('//'):
202
expanded = expanded[1:]
203
return expanded
204
205
206
# packages in the stdlib that may have installation metadata, but should not be
207
# considered 'installed'. this theoretically could be determined based on
208
# dist.location (py27:`sysconfig.get_paths()['stdlib']`,
209
# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may
210
# make this ineffective, so hard-coding
211
stdlib_pkgs = {"python", "wsgiref", "argparse"}
212
213
214
# windows detection, covers cpython and ironpython
215
WINDOWS = (sys.platform.startswith("win") or
216
(sys.platform == 'cli' and os.name == 'nt'))
217
218
219
def samefile(file1, file2):
220
# type: (str, str) -> bool
221
"""Provide an alternative for os.path.samefile on Windows/Python2"""
222
if hasattr(os.path, 'samefile'):
223
return os.path.samefile(file1, file2)
224
else:
225
path1 = os.path.normcase(os.path.abspath(file1))
226
path2 = os.path.normcase(os.path.abspath(file2))
227
return path1 == path2
228
229
230
if hasattr(shutil, 'get_terminal_size'):
231
def get_terminal_size():
232
# type: () -> Tuple[int, int]
233
"""
234
Returns a tuple (x, y) representing the width(x) and the height(y)
235
in characters of the terminal window.
236
"""
237
return tuple(shutil.get_terminal_size()) # type: ignore
238
else:
239
def get_terminal_size():
240
# type: () -> Tuple[int, int]
241
"""
242
Returns a tuple (x, y) representing the width(x) and the height(y)
243
in characters of the terminal window.
244
"""
245
def ioctl_GWINSZ(fd):
246
try:
247
import fcntl
248
import termios
249
import struct
250
cr = struct.unpack_from(
251
'hh',
252
fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678')
253
)
254
except Exception:
255
return None
256
if cr == (0, 0):
257
return None
258
return cr
259
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
260
if not cr:
261
if sys.platform != "win32":
262
try:
263
fd = os.open(os.ctermid(), os.O_RDONLY)
264
cr = ioctl_GWINSZ(fd)
265
os.close(fd)
266
except Exception:
267
pass
268
if not cr:
269
cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
270
return int(cr[1]), int(cr[0])
271
272