summaryrefslogtreecommitdiff
path: root/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils
diff options
context:
space:
mode:
authorShubham Saini <shubham6405@gmail.com>2019-08-05 08:32:33 +0000
committerShubham Saini <shubham6405@gmail.com>2019-08-05 08:32:33 +0000
commit227b2d30a8675b44918f9d9ca89b24144a938215 (patch)
tree9f8e6a28724514b6fdf463a9ab2067a7ef309b72 /venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils
parent842a8cfbbbdb1f92889d892e4859dbd5d40c5be8 (diff)
removing venv files
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils')
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/__init__.py0
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/appdirs.py258
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/deprecation.py77
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/encoding.py33
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/filesystem.py28
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/glibc.py84
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/hashes.py94
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/logging.py132
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py851
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/outdated.py163
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/packaging.py70
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/setuptools_build.py8
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/temp_dir.py82
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/typing.py29
-rw-r--r--venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/ui.py421
15 files changed, 0 insertions, 2330 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/__init__.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/appdirs.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/appdirs.py
deleted file mode 100644
index 0eb87ca..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/appdirs.py
+++ /dev/null
@@ -1,258 +0,0 @@
1"""
2This code was taken from https://github.com/ActiveState/appdirs and modified
3to suit our purposes.
4"""
5from __future__ import absolute_import
6
7import os
8import sys
9
10from pip._vendor.six import PY2, text_type
11
12from pip._internal.compat import WINDOWS, expanduser
13
14
15def user_cache_dir(appname):
16 r"""
17 Return full path to the user-specific cache dir for this application.
18
19 "appname" is the name of application.
20
21 Typical user cache directories are:
22 macOS: ~/Library/Caches/<AppName>
23 Unix: ~/.cache/<AppName> (XDG default)
24 Windows: C:\Users\<username>\AppData\Local\<AppName>\Cache
25
26 On Windows the only suggestion in the MSDN docs is that local settings go
27 in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the
28 non-roaming app data dir (the default returned by `user_data_dir`). Apps
29 typically put cache data somewhere *under* the given dir here. Some
30 examples:
31 ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
32 ...\Acme\SuperApp\Cache\1.0
33
34 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
35 """
36 if WINDOWS:
37 # Get the base path
38 path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
39
40 # When using Python 2, return paths as bytes on Windows like we do on
41 # other operating systems. See helper function docs for more details.
42 if PY2 and isinstance(path, text_type):
43 path = _win_path_to_bytes(path)
44
45 # Add our app name and Cache directory to it
46 path = os.path.join(path, appname, "Cache")
47 elif sys.platform == "darwin":
48 # Get the base path
49 path = expanduser("~/Library/Caches")
50
51 # Add our app name to it
52 path = os.path.join(path, appname)
53 else:
54 # Get the base path
55 path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache"))
56
57 # Add our app name to it
58 path = os.path.join(path, appname)
59
60 return path
61
62
63def user_data_dir(appname, roaming=False):
64 r"""
65 Return full path to the user-specific data dir for this application.
66
67 "appname" is the name of application.
68 If None, just the system directory is returned.
69 "roaming" (boolean, default False) can be set True to use the Windows
70 roaming appdata directory. That means that for users on a Windows
71 network setup for roaming profiles, this user data will be
72 sync'd on login. See
73 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
74 for a discussion of issues.
75
76 Typical user data directories are:
77 macOS: ~/Library/Application Support/<AppName>
78 if it exists, else ~/.config/<AppName>
79 Unix: ~/.local/share/<AppName> # or in
80 $XDG_DATA_HOME, if defined
81 Win XP (not roaming): C:\Documents and Settings\<username>\ ...
82 ...Application Data\<AppName>
83 Win XP (roaming): C:\Documents and Settings\<username>\Local ...
84 ...Settings\Application Data\<AppName>
85 Win 7 (not roaming): C:\\Users\<username>\AppData\Local\<AppName>
86 Win 7 (roaming): C:\\Users\<username>\AppData\Roaming\<AppName>
87
88 For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
89 That means, by default "~/.local/share/<AppName>".
90 """
91 if WINDOWS:
92 const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
93 path = os.path.join(os.path.normpath(_get_win_folder(const)), appname)
94 elif sys.platform == "darwin":
95 path = os.path.join(
96 expanduser('~/Library/Application Support/'),
97 appname,
98 ) if os.path.isdir(os.path.join(
99 expanduser('~/Library/Application Support/'),
100 appname,
101 )
102 ) else os.path.join(
103 expanduser('~/.config/'),
104 appname,
105 )
106 else:
107 path = os.path.join(
108 os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")),
109 appname,
110 )
111
112 return path
113
114
115def user_config_dir(appname, roaming=True):
116 """Return full path to the user-specific config dir for this application.
117
118 "appname" is the name of application.
119 If None, just the system directory is returned.
120 "roaming" (boolean, default True) can be set False to not use the
121 Windows roaming appdata directory. That means that for users on a
122 Windows network setup for roaming profiles, this user data will be
123 sync'd on login. See
124 <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
125 for a discussion of issues.
126
127 Typical user data directories are:
128 macOS: same as user_data_dir
129 Unix: ~/.config/<AppName>
130 Win *: same as user_data_dir
131
132 For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
133 That means, by default "~/.config/<AppName>".
134 """
135 if WINDOWS:
136 path = user_data_dir(appname, roaming=roaming)
137 elif sys.platform == "darwin":
138 path = user_data_dir(appname)
139 else:
140 path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config"))
141 path = os.path.join(path, appname)
142
143 return path
144
145
146# for the discussion regarding site_config_dirs locations
147# see <https://github.com/pypa/pip/issues/1733>
148def site_config_dirs(appname):
149 r"""Return a list of potential user-shared config dirs for this application.
150
151 "appname" is the name of application.
152
153 Typical user config directories are:
154 macOS: /Library/Application Support/<AppName>/
155 Unix: /etc or $XDG_CONFIG_DIRS[i]/<AppName>/ for each value in
156 $XDG_CONFIG_DIRS
157 Win XP: C:\Documents and Settings\All Users\Application ...
158 ...Data\<AppName>\
159 Vista: (Fail! "C:\ProgramData" is a hidden *system* directory
160 on Vista.)
161 Win 7: Hidden, but writeable on Win 7:
162 C:\ProgramData\<AppName>\
163 """
164 if WINDOWS:
165 path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
166 pathlist = [os.path.join(path, appname)]
167 elif sys.platform == 'darwin':
168 pathlist = [os.path.join('/Library/Application Support', appname)]
169 else:
170 # try looking in $XDG_CONFIG_DIRS
171 xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
172 if xdg_config_dirs:
173 pathlist = [
174 os.path.join(expanduser(x), appname)
175 for x in xdg_config_dirs.split(os.pathsep)
176 ]
177 else:
178 pathlist = []
179
180 # always look in /etc directly as well
181 pathlist.append('/etc')
182
183 return pathlist
184
185
186# -- Windows support functions --
187
188def _get_win_folder_from_registry(csidl_name):
189 """
190 This is a fallback technique at best. I'm not sure if using the
191 registry for this guarantees us the correct answer for all CSIDL_*
192 names.
193 """
194 import _winreg
195
196 shell_folder_name = {
197 "CSIDL_APPDATA": "AppData",
198 "CSIDL_COMMON_APPDATA": "Common AppData",
199 "CSIDL_LOCAL_APPDATA": "Local AppData",
200 }[csidl_name]
201
202 key = _winreg.OpenKey(
203 _winreg.HKEY_CURRENT_USER,
204 r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
205 )
206 directory, _type = _winreg.QueryValueEx(key, shell_folder_name)
207 return directory
208
209
210def _get_win_folder_with_ctypes(csidl_name):
211 csidl_const = {
212 "CSIDL_APPDATA": 26,
213 "CSIDL_COMMON_APPDATA": 35,
214 "CSIDL_LOCAL_APPDATA": 28,
215 }[csidl_name]
216
217 buf = ctypes.create_unicode_buffer(1024)
218 ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
219
220 # Downgrade to short path name if have highbit chars. See
221 # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
222 has_high_char = False
223 for c in buf:
224 if ord(c) > 255:
225 has_high_char = True
226 break
227 if has_high_char:
228 buf2 = ctypes.create_unicode_buffer(1024)
229 if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
230 buf = buf2
231
232 return buf.value
233
234
235if WINDOWS:
236 try:
237 import ctypes
238 _get_win_folder = _get_win_folder_with_ctypes
239 except ImportError:
240 _get_win_folder = _get_win_folder_from_registry
241
242
243def _win_path_to_bytes(path):
244 """Encode Windows paths to bytes. Only used on Python 2.
245
246 Motivation is to be consistent with other operating systems where paths
247 are also returned as bytes. This avoids problems mixing bytes and Unicode
248 elsewhere in the codebase. For more details and discussion see
249 <https://github.com/pypa/pip/issues/3463>.
250
251 If encoding using ASCII and MBCS fails, return the original Unicode path.
252 """
253 for encoding in ('ASCII', 'MBCS'):
254 try:
255 return path.encode(encoding)
256 except (UnicodeEncodeError, LookupError):
257 pass
258 return path
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/deprecation.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/deprecation.py
deleted file mode 100644
index c0e3884..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/deprecation.py
+++ /dev/null
@@ -1,77 +0,0 @@
1"""
2A module that implements tooling to enable easy warnings about deprecations.
3"""
4from __future__ import absolute_import
5
6import logging
7import warnings
8
9from pip._internal.utils.typing import MYPY_CHECK_RUNNING
10
11if MYPY_CHECK_RUNNING:
12 from typing import Any
13
14
15class PipDeprecationWarning(Warning):
16 pass
17
18
19class Pending(object):
20 pass
21
22
23class RemovedInPip11Warning(PipDeprecationWarning):
24 pass
25
26
27class RemovedInPip12Warning(PipDeprecationWarning, Pending):
28 pass
29
30
31# Warnings <-> Logging Integration
32
33
34_warnings_showwarning = None # type: Any
35
36
37def _showwarning(message, category, filename, lineno, file=None, line=None):
38 if file is not None:
39 if _warnings_showwarning is not None:
40 _warnings_showwarning(
41 message, category, filename, lineno, file, line,
42 )
43 else:
44 if issubclass(category, PipDeprecationWarning):
45 # We use a specially named logger which will handle all of the
46 # deprecation messages for pip.
47 logger = logging.getLogger("pip._internal.deprecations")
48
49 # This is purposely using the % formatter here instead of letting
50 # the logging module handle the interpolation. This is because we
51 # want it to appear as if someone typed this entire message out.
52 log_message = "DEPRECATION: %s" % message
53
54 # PipDeprecationWarnings that are Pending still have at least 2
55 # versions to go until they are removed so they can just be
56 # warnings. Otherwise, they will be removed in the very next
57 # version of pip. We want these to be more obvious so we use the
58 # ERROR logging level.
59 if issubclass(category, Pending):
60 logger.warning(log_message)
61 else:
62 logger.error(log_message)
63 else:
64 _warnings_showwarning(
65 message, category, filename, lineno, file, line,
66 )
67
68
69def install_warning_logger():
70 # Enable our Deprecation Warnings
71 warnings.simplefilter("default", PipDeprecationWarning, append=True)
72
73 global _warnings_showwarning
74
75 if _warnings_showwarning is None:
76 _warnings_showwarning = warnings.showwarning
77 warnings.showwarning = _showwarning
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/encoding.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/encoding.py
deleted file mode 100644
index 831f3f6..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/encoding.py
+++ /dev/null
@@ -1,33 +0,0 @@
1import codecs
2import locale
3import re
4import sys
5
6BOMS = [
7 (codecs.BOM_UTF8, 'utf8'),
8 (codecs.BOM_UTF16, 'utf16'),
9 (codecs.BOM_UTF16_BE, 'utf16-be'),
10 (codecs.BOM_UTF16_LE, 'utf16-le'),
11 (codecs.BOM_UTF32, 'utf32'),
12 (codecs.BOM_UTF32_BE, 'utf32-be'),
13 (codecs.BOM_UTF32_LE, 'utf32-le'),
14]
15
16ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)')
17
18
19def auto_decode(data):
20 """Check a bytes string for a BOM to correctly detect the encoding
21
22 Fallback to locale.getpreferredencoding(False) like open() on Python3"""
23 for bom, encoding in BOMS:
24 if data.startswith(bom):
25 return data[len(bom):].decode(encoding)
26 # Lets check the first two lines as in PEP263
27 for line in data.split(b'\n')[:2]:
28 if line[0:1] == b'#' and ENCODING_RE.search(line):
29 encoding = ENCODING_RE.search(line).groups()[0].decode('ascii')
30 return data.decode(encoding)
31 return data.decode(
32 locale.getpreferredencoding(False) or sys.getdefaultencoding(),
33 )
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/filesystem.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/filesystem.py
deleted file mode 100644
index 94fa2c6..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/filesystem.py
+++ /dev/null
@@ -1,28 +0,0 @@
1import os
2import os.path
3
4from pip._internal.compat import get_path_uid
5
6
7def check_path_owner(path):
8 # If we don't have a way to check the effective uid of this process, then
9 # we'll just assume that we own the directory.
10 if not hasattr(os, "geteuid"):
11 return True
12
13 previous = None
14 while path != previous:
15 if os.path.lexists(path):
16 # Check if path is writable by current user.
17 if os.geteuid() == 0:
18 # Special handling for root user in order to handle properly
19 # cases where users use sudo without -H flag.
20 try:
21 path_uid = get_path_uid(path)
22 except OSError:
23 return False
24 return path_uid == 0
25 else:
26 return os.access(path, os.W_OK)
27 else:
28 previous, path = path, os.path.dirname(path)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/glibc.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/glibc.py
deleted file mode 100644
index 5900a10..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/glibc.py
+++ /dev/null
@@ -1,84 +0,0 @@
1from __future__ import absolute_import
2
3import ctypes
4import re
5import warnings
6
7
8def glibc_version_string():
9 "Returns glibc version string, or None if not using glibc."
10
11 # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
12 # manpage says, "If filename is NULL, then the returned handle is for the
13 # main program". This way we can let the linker do the work to figure out
14 # which libc our process is actually using.
15 process_namespace = ctypes.CDLL(None)
16 try:
17 gnu_get_libc_version = process_namespace.gnu_get_libc_version
18 except AttributeError:
19 # Symbol doesn't exist -> therefore, we are not linked to
20 # glibc.
21 return None
22
23 # Call gnu_get_libc_version, which returns a string like "2.5"
24 gnu_get_libc_version.restype = ctypes.c_char_p
25 version_str = gnu_get_libc_version()
26 # py2 / py3 compatibility:
27 if not isinstance(version_str, str):
28 version_str = version_str.decode("ascii")
29
30 return version_str
31
32
33# Separated out from have_compatible_glibc for easier unit testing
34def check_glibc_version(version_str, required_major, minimum_minor):
35 # Parse string and check against requested version.
36 #
37 # We use a regexp instead of str.split because we want to discard any
38 # random junk that might come after the minor version -- this might happen
39 # in patched/forked versions of glibc (e.g. Linaro's version of glibc
40 # uses version strings like "2.20-2014.11"). See gh-3588.
41 m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
42 if not m:
43 warnings.warn("Expected glibc version with 2 components major.minor,"
44 " got: %s" % version_str, RuntimeWarning)
45 return False
46 return (int(m.group("major")) == required_major and
47 int(m.group("minor")) >= minimum_minor)
48
49
50def have_compatible_glibc(required_major, minimum_minor):
51 version_str = glibc_version_string()
52 if version_str is None:
53 return False
54 return check_glibc_version(version_str, required_major, minimum_minor)
55
56
57# platform.libc_ver regularly returns completely nonsensical glibc
58# versions. E.g. on my computer, platform says:
59#
60# ~$ python2.7 -c 'import platform; print(platform.libc_ver())'
61# ('glibc', '2.7')
62# ~$ python3.5 -c 'import platform; print(platform.libc_ver())'
63# ('glibc', '2.9')
64#
65# But the truth is:
66#
67# ~$ ldd --version
68# ldd (Debian GLIBC 2.22-11) 2.22
69#
70# This is unfortunate, because it means that the linehaul data on libc
71# versions that was generated by pip 8.1.2 and earlier is useless and
72# misleading. Solution: instead of using platform, use our code that actually
73# works.
74def libc_ver():
75 """Try to determine the glibc version
76
77 Returns a tuple of strings (lib, version) which default to empty strings
78 in case the lookup fails.
79 """
80 glibc_version = glibc_version_string()
81 if glibc_version is None:
82 return ("", "")
83 else:
84 return ("glibc", glibc_version)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/hashes.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/hashes.py
deleted file mode 100644
index 8cf6367..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/hashes.py
+++ /dev/null
@@ -1,94 +0,0 @@
1from __future__ import absolute_import
2
3import hashlib
4
5from pip._vendor.six import iteritems, iterkeys, itervalues
6
7from pip._internal.exceptions import (
8 HashMismatch, HashMissing, InstallationError,
9)
10from pip._internal.utils.misc import read_chunks
11
12# The recommended hash algo of the moment. Change this whenever the state of
13# the art changes; it won't hurt backward compatibility.
14FAVORITE_HASH = 'sha256'
15
16
17# Names of hashlib algorithms allowed by the --hash option and ``pip hash``
18# Currently, those are the ones at least as collision-resistant as sha256.
19STRONG_HASHES = ['sha256', 'sha384', 'sha512']
20
21
22class Hashes(object):
23 """A wrapper that builds multiple hashes at once and checks them against
24 known-good values
25
26 """
27 def __init__(self, hashes=None):
28 """
29 :param hashes: A dict of algorithm names pointing to lists of allowed
30 hex digests
31 """
32 self._allowed = {} if hashes is None else hashes
33
34 def check_against_chunks(self, chunks):
35 """Check good hashes against ones built from iterable of chunks of
36 data.
37
38 Raise HashMismatch if none match.
39
40 """
41 gots = {}
42 for hash_name in iterkeys(self._allowed):
43 try:
44 gots[hash_name] = hashlib.new(hash_name)
45 except (ValueError, TypeError):
46 raise InstallationError('Unknown hash name: %s' % hash_name)
47
48 for chunk in chunks:
49 for hash in itervalues(gots):
50 hash.update(chunk)
51
52 for hash_name, got in iteritems(gots):
53 if got.hexdigest() in self._allowed[hash_name]:
54 return
55 self._raise(gots)
56
57 def _raise(self, gots):
58 raise HashMismatch(self._allowed, gots)
59
60 def check_against_file(self, file):
61 """Check good hashes against a file-like object
62
63 Raise HashMismatch if none match.
64
65 """
66 return self.check_against_chunks(read_chunks(file))
67
68 def check_against_path(self, path):
69 with open(path, 'rb') as file:
70 return self.check_against_file(file)
71
72 def __nonzero__(self):
73 """Return whether I know any known-good hashes."""
74 return bool(self._allowed)
75
76 def __bool__(self):
77 return self.__nonzero__()
78
79
80class MissingHashes(Hashes):
81 """A workalike for Hashes used when we're missing a hash for a requirement
82
83 It computes the actual hash of the requirement and raises a HashMissing
84 exception showing it to the user.
85
86 """
87 def __init__(self):
88 """Don't offer the ``hashes`` kwarg."""
89 # Pass our favorite hash in to generate a "gotten hash". With the
90 # empty list, it will never match, so an error will always raise.
91 super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []})
92
93 def _raise(self, gots):
94 raise HashMissing(gots[FAVORITE_HASH].hexdigest())
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/logging.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/logging.py
deleted file mode 100644
index 1fb3e8a..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/logging.py
+++ /dev/null
@@ -1,132 +0,0 @@
1from __future__ import absolute_import
2
3import contextlib
4import logging
5import logging.handlers
6import os
7
8from pip._internal.compat import WINDOWS
9from pip._internal.utils.misc import ensure_dir
10
11try:
12 import threading
13except ImportError:
14 import dummy_threading as threading # type: ignore
15
16
17try:
18 from pip._vendor import colorama
19# Lots of different errors can come from this, including SystemError and
20# ImportError.
21except Exception:
22 colorama = None
23
24
25_log_state = threading.local()
26_log_state.indentation = 0
27
28
29@contextlib.contextmanager
30def indent_log(num=2):
31 """
32 A context manager which will cause the log output to be indented for any
33 log messages emitted inside it.
34 """
35 _log_state.indentation += num
36 try:
37 yield
38 finally:
39 _log_state.indentation -= num
40
41
42def get_indentation():
43 return getattr(_log_state, 'indentation', 0)
44
45
46class IndentingFormatter(logging.Formatter):
47
48 def format(self, record):
49 """
50 Calls the standard formatter, but will indent all of the log messages
51 by our current indentation level.
52 """
53 formatted = logging.Formatter.format(self, record)
54 formatted = "".join([
55 (" " * get_indentation()) + line
56 for line in formatted.splitlines(True)
57 ])
58 return formatted
59
60
61def _color_wrap(*colors):
62 def wrapped(inp):
63 return "".join(list(colors) + [inp, colorama.Style.RESET_ALL])
64 return wrapped
65
66
67class ColorizedStreamHandler(logging.StreamHandler):
68
69 # Don't build up a list of colors if we don't have colorama
70 if colorama:
71 COLORS = [
72 # This needs to be in order from highest logging level to lowest.
73 (logging.ERROR, _color_wrap(colorama.Fore.RED)),
74 (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)),
75 ]
76 else:
77 COLORS = []
78
79 def __init__(self, stream=None, no_color=None):
80 logging.StreamHandler.__init__(self, stream)
81 self._no_color = no_color
82
83 if WINDOWS and colorama:
84 self.stream = colorama.AnsiToWin32(self.stream)
85
86 def should_color(self):
87 # Don't colorize things if we do not have colorama or if told not to
88 if not colorama or self._no_color:
89 return False
90
91 real_stream = (
92 self.stream if not isinstance(self.stream, colorama.AnsiToWin32)
93 else self.stream.wrapped
94 )
95
96 # If the stream is a tty we should color it
97 if hasattr(real_stream, "isatty") and real_stream.isatty():
98 return True
99
100 # If we have an ASNI term we should color it
101 if os.environ.get("TERM") == "ANSI":
102 return True
103
104 # If anything else we should not color it
105 return False
106
107 def format(self, record):
108 msg = logging.StreamHandler.format(self, record)
109
110 if self.should_color():
111 for level, color in self.COLORS:
112 if record.levelno >= level:
113 msg = color(msg)
114 break
115
116 return msg
117
118
119class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler):
120
121 def _open(self):
122 ensure_dir(os.path.dirname(self.baseFilename))
123 return logging.handlers.RotatingFileHandler._open(self)
124
125
126class MaxLevelFilter(logging.Filter):
127
128 def __init__(self, level):
129 self.level = level
130
131 def filter(self, record):
132 return record.levelno < self.level
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py
deleted file mode 100644
index db84a7c..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/misc.py
+++ /dev/null
@@ -1,851 +0,0 @@
1from __future__ import absolute_import
2
3import contextlib
4import errno
5import io
6import locale
7# we have a submodule named 'logging' which would shadow this if we used the
8# regular name:
9import logging as std_logging
10import os
11import posixpath
12import re
13import shutil
14import stat
15import subprocess
16import sys
17import tarfile
18import zipfile
19from collections import deque
20
21from pip._vendor import pkg_resources
22# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is
23# why we ignore the type on this import.
24from pip._vendor.retrying import retry # type: ignore
25from pip._vendor.six import PY2
26from pip._vendor.six.moves import input
27
28from pip._internal.compat import console_to_str, expanduser, stdlib_pkgs
29from pip._internal.exceptions import InstallationError
30from pip._internal.locations import (
31 running_under_virtualenv, site_packages, user_site, virtualenv_no_global,
32 write_delete_marker_file,
33)
34
35if PY2:
36 from io import BytesIO as StringIO
37else:
38 from io import StringIO
39
40__all__ = ['rmtree', 'display_path', 'backup_dir',
41 'ask', 'splitext',
42 'format_size', 'is_installable_dir',
43 'is_svn_page', 'file_contents',
44 'split_leading_dir', 'has_leading_dir',
45 'normalize_path',
46 'renames', 'get_prog',
47 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess',
48 'captured_stdout', 'ensure_dir',
49 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS',
50 'get_installed_version']
51
52
53logger = std_logging.getLogger(__name__)
54
55BZ2_EXTENSIONS = ('.tar.bz2', '.tbz')
56XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', '.tar.lz', '.tar.lzma')
57ZIP_EXTENSIONS = ('.zip', '.whl')
58TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar')
59ARCHIVE_EXTENSIONS = (
60 ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS)
61SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS
62try:
63 import bz2 # noqa
64 SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS
65except ImportError:
66 logger.debug('bz2 module is not available')
67
68try:
69 # Only for Python 3.3+
70 import lzma # noqa
71 SUPPORTED_EXTENSIONS += XZ_EXTENSIONS
72except ImportError:
73 logger.debug('lzma module is not available')
74
75
76def import_or_raise(pkg_or_module_string, ExceptionType, *args, **kwargs):
77 try:
78 return __import__(pkg_or_module_string)
79 except ImportError:
80 raise ExceptionType(*args, **kwargs)
81
82
83def ensure_dir(path):
84 """os.path.makedirs without EEXIST."""
85 try:
86 os.makedirs(path)
87 except OSError as e:
88 if e.errno != errno.EEXIST:
89 raise
90
91
92def get_prog():
93 try:
94 prog = os.path.basename(sys.argv[0])
95 if prog in ('__main__.py', '-c'):
96 return "%s -m pip" % sys.executable
97 else:
98 return prog
99 except (AttributeError, TypeError, IndexError):
100 pass
101 return 'pip'
102
103
104# Retry every half second for up to 3 seconds
105@retry(stop_max_delay=3000, wait_fixed=500)
106def rmtree(dir, ignore_errors=False):
107 shutil.rmtree(dir, ignore_errors=ignore_errors,
108 onerror=rmtree_errorhandler)
109
110
111def rmtree_errorhandler(func, path, exc_info):
112 """On Windows, the files in .svn are read-only, so when rmtree() tries to
113 remove them, an exception is thrown. We catch that here, remove the
114 read-only attribute, and hopefully continue without problems."""
115 # if file type currently read only
116 if os.stat(path).st_mode & stat.S_IREAD:
117 # convert to read/write
118 os.chmod(path, stat.S_IWRITE)
119 # use the original function to repeat the operation
120 func(path)
121 return
122 else:
123 raise
124
125
126def display_path(path):
127 """Gives the display value for a given path, making it relative to cwd
128 if possible."""
129 path = os.path.normcase(os.path.abspath(path))
130 if sys.version_info[0] == 2:
131 path = path.decode(sys.getfilesystemencoding(), 'replace')
132 path = path.encode(sys.getdefaultencoding(), 'replace')
133 if path.startswith(os.getcwd() + os.path.sep):
134 path = '.' + path[len(os.getcwd()):]
135 return path
136
137
138def backup_dir(dir, ext='.bak'):
139 """Figure out the name of a directory to back up the given dir to
140 (adding .bak, .bak2, etc)"""
141 n = 1
142 extension = ext
143 while os.path.exists(dir + extension):
144 n += 1
145 extension = ext + str(n)
146 return dir + extension
147
148
149def ask_path_exists(message, options):
150 for action in os.environ.get('PIP_EXISTS_ACTION', '').split():
151 if action in options:
152 return action
153 return ask(message, options)
154
155
156def ask(message, options):
157 """Ask the message interactively, with the given possible responses"""
158 while 1:
159 if os.environ.get('PIP_NO_INPUT'):
160 raise Exception(
161 'No input was expected ($PIP_NO_INPUT set); question: %s' %
162 message
163 )
164 response = input(message)
165 response = response.strip().lower()
166 if response not in options:
167 print(
168 'Your response (%r) was not one of the expected responses: '
169 '%s' % (response, ', '.join(options))
170 )
171 else:
172 return response
173
174
175def format_size(bytes):
176 if bytes > 1000 * 1000:
177 return '%.1fMB' % (bytes / 1000.0 / 1000)
178 elif bytes > 10 * 1000:
179 return '%ikB' % (bytes / 1000)
180 elif bytes > 1000:
181 return '%.1fkB' % (bytes / 1000.0)
182 else:
183 return '%ibytes' % bytes
184
185
186def is_installable_dir(path):
187 """Return True if `path` is a directory containing a setup.py file."""
188 if not os.path.isdir(path):
189 return False
190 setup_py = os.path.join(path, 'setup.py')
191 if os.path.isfile(setup_py):
192 return True
193 return False
194
195
196def is_svn_page(html):
197 """
198 Returns true if the page appears to be the index page of an svn repository
199 """
200 return (re.search(r'<title>[^<]*Revision \d+:', html) and
201 re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I))
202
203
204def file_contents(filename):
205 with open(filename, 'rb') as fp:
206 return fp.read().decode('utf-8')
207
208
209def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE):
210 """Yield pieces of data from a file-like object until EOF."""
211 while True:
212 chunk = file.read(size)
213 if not chunk:
214 break
215 yield chunk
216
217
218def split_leading_dir(path):
219 path = path.lstrip('/').lstrip('\\')
220 if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or
221 '\\' not in path):
222 return path.split('/', 1)
223 elif '\\' in path:
224 return path.split('\\', 1)
225 else:
226 return path, ''
227
228
229def has_leading_dir(paths):
230 """Returns true if all the paths have the same leading path name
231 (i.e., everything is in one subdirectory in an archive)"""
232 common_prefix = None
233 for path in paths:
234 prefix, rest = split_leading_dir(path)
235 if not prefix:
236 return False
237 elif common_prefix is None:
238 common_prefix = prefix
239 elif prefix != common_prefix:
240 return False
241 return True
242
243
244def normalize_path(path, resolve_symlinks=True):
245 """
246 Convert a path to its canonical, case-normalized, absolute version.
247
248 """
249 path = expanduser(path)
250 if resolve_symlinks:
251 path = os.path.realpath(path)
252 else:
253 path = os.path.abspath(path)
254 return os.path.normcase(path)
255
256
257def splitext(path):
258 """Like os.path.splitext, but take off .tar too"""
259 base, ext = posixpath.splitext(path)
260 if base.lower().endswith('.tar'):
261 ext = base[-4:] + ext
262 base = base[:-4]
263 return base, ext
264
265
266def renames(old, new):
267 """Like os.renames(), but handles renaming across devices."""
268 # Implementation borrowed from os.renames().
269 head, tail = os.path.split(new)
270 if head and tail and not os.path.exists(head):
271 os.makedirs(head)
272
273 shutil.move(old, new)
274
275 head, tail = os.path.split(old)
276 if head and tail:
277 try:
278 os.removedirs(head)
279 except OSError:
280 pass
281
282
283def is_local(path):
284 """
285 Return True if path is within sys.prefix, if we're running in a virtualenv.
286
287 If we're not in a virtualenv, all paths are considered "local."
288
289 """
290 if not running_under_virtualenv():
291 return True
292 return normalize_path(path).startswith(normalize_path(sys.prefix))
293
294
295def dist_is_local(dist):
296 """
297 Return True if given Distribution object is installed locally
298 (i.e. within current virtualenv).
299
300 Always True if we're not in a virtualenv.
301
302 """
303 return is_local(dist_location(dist))
304
305
306def dist_in_usersite(dist):
307 """
308 Return True if given Distribution is installed in user site.
309 """
310 norm_path = normalize_path(dist_location(dist))
311 return norm_path.startswith(normalize_path(user_site))
312
313
314def dist_in_site_packages(dist):
315 """
316 Return True if given Distribution is installed in
317 sysconfig.get_python_lib().
318 """
319 return normalize_path(
320 dist_location(dist)
321 ).startswith(normalize_path(site_packages))
322
323
324def dist_is_editable(dist):
325 """Is distribution an editable install?"""
326 for path_item in sys.path:
327 egg_link = os.path.join(path_item, dist.project_name + '.egg-link')
328 if os.path.isfile(egg_link):
329 return True
330 return False
331
332
333def get_installed_distributions(local_only=True,
334 skip=stdlib_pkgs,
335 include_editables=True,
336 editables_only=False,
337 user_only=False):
338 """
339 Return a list of installed Distribution objects.
340
341 If ``local_only`` is True (default), only return installations
342 local to the current virtualenv, if in a virtualenv.
343
344 ``skip`` argument is an iterable of lower-case project names to
345 ignore; defaults to stdlib_pkgs
346
347 If ``include_editables`` is False, don't report editables.
348
349 If ``editables_only`` is True , only report editables.
350
351 If ``user_only`` is True , only report installations in the user
352 site directory.
353
354 """
355 if local_only:
356 local_test = dist_is_local
357 else:
358 def local_test(d):
359 return True
360
361 if include_editables:
362 def editable_test(d):
363 return True
364 else:
365 def editable_test(d):
366 return not dist_is_editable(d)
367
368 if editables_only:
369 def editables_only_test(d):
370 return dist_is_editable(d)
371 else:
372 def editables_only_test(d):
373 return True
374
375 if user_only:
376 user_test = dist_in_usersite
377 else:
378 def user_test(d):
379 return True
380
381 return [d for d in pkg_resources.working_set
382 if local_test(d) and
383 d.key not in skip and
384 editable_test(d) and
385 editables_only_test(d) and
386 user_test(d)
387 ]
388
389
390def egg_link_path(dist):
391 """
392 Return the path for the .egg-link file if it exists, otherwise, None.
393
394 There's 3 scenarios:
395 1) not in a virtualenv
396 try to find in site.USER_SITE, then site_packages
397 2) in a no-global virtualenv
398 try to find in site_packages
399 3) in a yes-global virtualenv
400 try to find in site_packages, then site.USER_SITE
401 (don't look in global location)
402
403 For #1 and #3, there could be odd cases, where there's an egg-link in 2
404 locations.
405
406 This method will just return the first one found.
407 """
408 sites = []
409 if running_under_virtualenv():
410 if virtualenv_no_global():
411 sites.append(site_packages)
412 else:
413 sites.append(site_packages)
414 if user_site:
415 sites.append(user_site)
416 else:
417 if user_site:
418 sites.append(user_site)
419 sites.append(site_packages)
420
421 for site in sites:
422 egglink = os.path.join(site, dist.project_name) + '.egg-link'
423 if os.path.isfile(egglink):
424 return egglink
425
426
427def dist_location(dist):
428 """
429 Get the site-packages location of this distribution. Generally
430 this is dist.location, except in the case of develop-installed
431 packages, where dist.location is the source code location, and we
432 want to know where the egg-link file is.
433
434 """
435 egg_link = egg_link_path(dist)
436 if egg_link:
437 return egg_link
438 return dist.location
439
440
441def current_umask():
442 """Get the current umask which involves having to set it temporarily."""
443 mask = os.umask(0)
444 os.umask(mask)
445 return mask
446
447
448def unzip_file(filename, location, flatten=True):
449 """
450 Unzip the file (with path `filename`) to the destination `location`. All
451 files are written based on system defaults and umask (i.e. permissions are
452 not preserved), except that regular file members with any execute
453 permissions (user, group, or world) have "chmod +x" applied after being
454 written. Note that for windows, any execute changes using os.chmod are
455 no-ops per the python docs.
456 """
457 ensure_dir(location)
458 zipfp = open(filename, 'rb')
459 try:
460 zip = zipfile.ZipFile(zipfp, allowZip64=True)
461 leading = has_leading_dir(zip.namelist()) and flatten
462 for info in zip.infolist():
463 name = info.filename
464 data = zip.read(name)
465 fn = name
466 if leading:
467 fn = split_leading_dir(name)[1]
468 fn = os.path.join(location, fn)
469 dir = os.path.dirname(fn)
470 if fn.endswith('/') or fn.endswith('\\'):
471 # A directory
472 ensure_dir(fn)
473 else:
474 ensure_dir(dir)
475 fp = open(fn, 'wb')
476 try:
477 fp.write(data)
478 finally:
479 fp.close()
480 mode = info.external_attr >> 16
481 # if mode and regular file and any execute permissions for
482 # user/group/world?
483 if mode and stat.S_ISREG(mode) and mode & 0o111:
484 # make dest file have execute for user/group/world
485 # (chmod +x) no-op on windows per python docs
486 os.chmod(fn, (0o777 - current_umask() | 0o111))
487 finally:
488 zipfp.close()
489
490
491def untar_file(filename, location):
492 """
493 Untar the file (with path `filename`) to the destination `location`.
494 All files are written based on system defaults and umask (i.e. permissions
495 are not preserved), except that regular file members with any execute
496 permissions (user, group, or world) have "chmod +x" applied after being
497 written. Note that for windows, any execute changes using os.chmod are
498 no-ops per the python docs.
499 """
500 ensure_dir(location)
501 if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
502 mode = 'r:gz'
503 elif filename.lower().endswith(BZ2_EXTENSIONS):
504 mode = 'r:bz2'
505 elif filename.lower().endswith(XZ_EXTENSIONS):
506 mode = 'r:xz'
507 elif filename.lower().endswith('.tar'):
508 mode = 'r'
509 else:
510 logger.warning(
511 'Cannot determine compression type for file %s', filename,
512 )
513 mode = 'r:*'
514 tar = tarfile.open(filename, mode)
515 try:
516 # note: python<=2.5 doesn't seem to know about pax headers, filter them
517 leading = has_leading_dir([
518 member.name for member in tar.getmembers()
519 if member.name != 'pax_global_header'
520 ])
521 for member in tar.getmembers():
522 fn = member.name
523 if fn == 'pax_global_header':
524 continue
525 if leading:
526 fn = split_leading_dir(fn)[1]
527 path = os.path.join(location, fn)
528 if member.isdir():
529 ensure_dir(path)
530 elif member.issym():
531 try:
532 tar._extract_member(member, path)
533 except Exception as exc:
534 # Some corrupt tar files seem to produce this
535 # (specifically bad symlinks)
536 logger.warning(
537 'In the tar file %s the member %s is invalid: %s',
538 filename, member.name, exc,
539 )
540 continue
541 else:
542 try:
543 fp = tar.extractfile(member)
544 except (KeyError, AttributeError) as exc:
545 # Some corrupt tar files seem to produce this
546 # (specifically bad symlinks)
547 logger.warning(
548 'In the tar file %s the member %s is invalid: %s',
549 filename, member.name, exc,
550 )
551 continue
552 ensure_dir(os.path.dirname(path))
553 with open(path, 'wb') as destfp:
554 shutil.copyfileobj(fp, destfp)
555 fp.close()
556 # Update the timestamp (useful for cython compiled files)
557 tar.utime(member, path)
558 # member have any execute permissions for user/group/world?
559 if member.mode & 0o111:
560 # make dest file have execute for user/group/world
561 # no-op on windows per python docs
562 os.chmod(path, (0o777 - current_umask() | 0o111))
563 finally:
564 tar.close()
565
566
567def unpack_file(filename, location, content_type, link):
568 filename = os.path.realpath(filename)
569 if (content_type == 'application/zip' or
570 filename.lower().endswith(ZIP_EXTENSIONS) or
571 zipfile.is_zipfile(filename)):
572 unzip_file(
573 filename,
574 location,
575 flatten=not filename.endswith('.whl')
576 )
577 elif (content_type == 'application/x-gzip' or
578 tarfile.is_tarfile(filename) or
579 filename.lower().endswith(
580 TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)):
581 untar_file(filename, location)
582 elif (content_type and content_type.startswith('text/html') and
583 is_svn_page(file_contents(filename))):
584 # We don't really care about this
585 from pip._internal.vcs.subversion import Subversion
586 Subversion('svn+' + link.url).unpack(location)
587 else:
588 # FIXME: handle?
589 # FIXME: magic signatures?
590 logger.critical(
591 'Cannot unpack file %s (downloaded from %s, content-type: %s); '
592 'cannot detect archive format',
593 filename, location, content_type,
594 )
595 raise InstallationError(
596 'Cannot determine archive format of %s' % location
597 )
598
599
600def call_subprocess(cmd, show_stdout=True, cwd=None,
601 on_returncode='raise',
602 command_desc=None,
603 extra_environ=None, unset_environ=None, spinner=None):
604 """
605 Args:
606 unset_environ: an iterable of environment variable names to unset
607 prior to calling subprocess.Popen().
608 """
609 if unset_environ is None:
610 unset_environ = []
611 # This function's handling of subprocess output is confusing and I
612 # previously broke it terribly, so as penance I will write a long comment
613 # explaining things.
614 #
615 # The obvious thing that affects output is the show_stdout=
616 # kwarg. show_stdout=True means, let the subprocess write directly to our
617 # stdout. Even though it is nominally the default, it is almost never used
618 # inside pip (and should not be used in new code without a very good
619 # reason); as of 2016-02-22 it is only used in a few places inside the VCS
620 # wrapper code. Ideally we should get rid of it entirely, because it
621 # creates a lot of complexity here for a rarely used feature.
622 #
623 # Most places in pip set show_stdout=False. What this means is:
624 # - We connect the child stdout to a pipe, which we read.
625 # - By default, we hide the output but show a spinner -- unless the
626 # subprocess exits with an error, in which case we show the output.
627 # - If the --verbose option was passed (= loglevel is DEBUG), then we show
628 # the output unconditionally. (But in this case we don't want to show
629 # the output a second time if it turns out that there was an error.)
630 #
631 # stderr is always merged with stdout (even if show_stdout=True).
632 if show_stdout:
633 stdout = None
634 else:
635 stdout = subprocess.PIPE
636 if command_desc is None:
637 cmd_parts = []
638 for part in cmd:
639 if ' ' in part or '\n' in part or '"' in part or "'" in part:
640 part = '"%s"' % part.replace('"', '\\"')
641 cmd_parts.append(part)
642 command_desc = ' '.join(cmd_parts)
643 logger.debug("Running command %s", command_desc)
644 env = os.environ.copy()
645 if extra_environ:
646 env.update(extra_environ)
647 for name in unset_environ:
648 env.pop(name, None)
649 try:
650 proc = subprocess.Popen(
651 cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE,
652 stdout=stdout, cwd=cwd, env=env,
653 )
654 proc.stdin.close()
655 except Exception as exc:
656 logger.critical(
657 "Error %s while executing command %s", exc, command_desc,
658 )
659 raise
660 all_output = []
661 if stdout is not None:
662 while True:
663 line = console_to_str(proc.stdout.readline())
664 if not line:
665 break
666 line = line.rstrip()
667 all_output.append(line + '\n')
668 if logger.getEffectiveLevel() <= std_logging.DEBUG:
669 # Show the line immediately
670 logger.debug(line)
671 else:
672 # Update the spinner
673 if spinner is not None:
674 spinner.spin()
675 try:
676 proc.wait()
677 finally:
678 if proc.stdout:
679 proc.stdout.close()
680 if spinner is not None:
681 if proc.returncode:
682 spinner.finish("error")
683 else:
684 spinner.finish("done")
685 if proc.returncode:
686 if on_returncode == 'raise':
687 if (logger.getEffectiveLevel() > std_logging.DEBUG and
688 not show_stdout):
689 logger.info(
690 'Complete output from command %s:', command_desc,
691 )
692 logger.info(
693 ''.join(all_output) +
694 '\n----------------------------------------'
695 )
696 raise InstallationError(
697 'Command "%s" failed with error code %s in %s'
698 % (command_desc, proc.returncode, cwd))
699 elif on_returncode == 'warn':
700 logger.warning(
701 'Command "%s" had error code %s in %s',
702 command_desc, proc.returncode, cwd,
703 )
704 elif on_returncode == 'ignore':
705 pass
706 else:
707 raise ValueError('Invalid value: on_returncode=%s' %
708 repr(on_returncode))
709 if not show_stdout:
710 return ''.join(all_output)
711
712
713def read_text_file(filename):
714 """Return the contents of *filename*.
715
716 Try to decode the file contents with utf-8, the preferred system encoding
717 (e.g., cp1252 on some Windows machines), and latin1, in that order.
718 Decoding a byte string with latin1 will never raise an error. In the worst
719 case, the returned string will contain some garbage characters.
720
721 """
722 with open(filename, 'rb') as fp:
723 data = fp.read()
724
725 encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1']
726 for enc in encodings:
727 try:
728 data = data.decode(enc)
729 except UnicodeDecodeError:
730 continue
731 break
732
733 assert type(data) != bytes # Latin1 should have worked.
734 return data
735
736
737def _make_build_dir(build_dir):
738 os.makedirs(build_dir)
739 write_delete_marker_file(build_dir)
740
741
742class FakeFile(object):
743 """Wrap a list of lines in an object with readline() to make
744 ConfigParser happy."""
745 def __init__(self, lines):
746 self._gen = (l for l in lines)
747
748 def readline(self):
749 try:
750 try:
751 return next(self._gen)
752 except NameError:
753 return self._gen.next()
754 except StopIteration:
755 return ''
756
757 def __iter__(self):
758 return self._gen
759
760
761class StreamWrapper(StringIO):
762
763 @classmethod
764 def from_stream(cls, orig_stream):
765 cls.orig_stream = orig_stream
766 return cls()
767
768 # compileall.compile_dir() needs stdout.encoding to print to stdout
769 @property
770 def encoding(self):
771 return self.orig_stream.encoding
772
773
774@contextlib.contextmanager
775def captured_output(stream_name):
776 """Return a context manager used by captured_stdout/stdin/stderr
777 that temporarily replaces the sys stream *stream_name* with a StringIO.
778
779 Taken from Lib/support/__init__.py in the CPython repo.
780 """
781 orig_stdout = getattr(sys, stream_name)
782 setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout))
783 try:
784 yield getattr(sys, stream_name)
785 finally:
786 setattr(sys, stream_name, orig_stdout)
787
788
789def captured_stdout():
790 """Capture the output of sys.stdout:
791
792 with captured_stdout() as stdout:
793 print('hello')
794 self.assertEqual(stdout.getvalue(), 'hello\n')
795
796 Taken from Lib/support/__init__.py in the CPython repo.
797 """
798 return captured_output('stdout')
799
800
801class cached_property(object):
802 """A property that is only computed once per instance and then replaces
803 itself with an ordinary attribute. Deleting the attribute resets the
804 property.
805
806 Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175
807 """
808
809 def __init__(self, func):
810 self.__doc__ = getattr(func, '__doc__')
811 self.func = func
812
813 def __get__(self, obj, cls):
814 if obj is None:
815 # We're being accessed from the class itself, not from an object
816 return self
817 value = obj.__dict__[self.func.__name__] = self.func(obj)
818 return value
819
820
821def get_installed_version(dist_name, lookup_dirs=None):
822 """Get the installed version of dist_name avoiding pkg_resources cache"""
823 # Create a requirement that we'll look for inside of setuptools.
824 req = pkg_resources.Requirement.parse(dist_name)
825
826 # We want to avoid having this cached, so we need to construct a new
827 # working set each time.
828 if lookup_dirs is None:
829 working_set = pkg_resources.WorkingSet()
830 else:
831 working_set = pkg_resources.WorkingSet(lookup_dirs)
832
833 # Get the installed distribution from our working set
834 dist = working_set.find(req)
835
836 # Check to see if we got an installed distribution or not, if we did
837 # we want to return it's version.
838 return dist.version if dist else None
839
840
841def consume(iterator):
842 """Consume an iterable at C speed."""
843 deque(iterator, maxlen=0)
844
845
846# Simulates an enum
847def enum(*sequential, **named):
848 enums = dict(zip(sequential, range(len(sequential))), **named)
849 reverse = {value: key for key, value in enums.items()}
850 enums['reverse_mapping'] = reverse
851 return type('Enum', (), enums)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/outdated.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/outdated.py
deleted file mode 100644
index f4572ab..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/outdated.py
+++ /dev/null
@@ -1,163 +0,0 @@
1from __future__ import absolute_import
2
3import datetime
4import json
5import logging
6import os.path
7import sys
8
9from pip._vendor import lockfile
10from pip._vendor.packaging import version as packaging_version
11
12from pip._internal.compat import WINDOWS
13from pip._internal.index import PackageFinder
14from pip._internal.locations import USER_CACHE_DIR, running_under_virtualenv
15from pip._internal.utils.filesystem import check_path_owner
16from pip._internal.utils.misc import ensure_dir, get_installed_version
17
18SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ"
19
20
21logger = logging.getLogger(__name__)
22
23
24class VirtualenvSelfCheckState(object):
25 def __init__(self):
26 self.statefile_path = os.path.join(sys.prefix, "pip-selfcheck.json")
27
28 # Load the existing state
29 try:
30 with open(self.statefile_path) as statefile:
31 self.state = json.load(statefile)
32 except (IOError, ValueError):
33 self.state = {}
34
35 def save(self, pypi_version, current_time):
36 # Attempt to write out our version check file
37 with open(self.statefile_path, "w") as statefile:
38 json.dump(
39 {
40 "last_check": current_time.strftime(SELFCHECK_DATE_FMT),
41 "pypi_version": pypi_version,
42 },
43 statefile,
44 sort_keys=True,
45 separators=(",", ":")
46 )
47
48
49class GlobalSelfCheckState(object):
50 def __init__(self):
51 self.statefile_path = os.path.join(USER_CACHE_DIR, "selfcheck.json")
52
53 # Load the existing state
54 try:
55 with open(self.statefile_path) as statefile:
56 self.state = json.load(statefile)[sys.prefix]
57 except (IOError, ValueError, KeyError):
58 self.state = {}
59
60 def save(self, pypi_version, current_time):
61 # Check to make sure that we own the directory
62 if not check_path_owner(os.path.dirname(self.statefile_path)):
63 return
64
65 # Now that we've ensured the directory is owned by this user, we'll go
66 # ahead and make sure that all our directories are created.
67 ensure_dir(os.path.dirname(self.statefile_path))
68
69 # Attempt to write out our version check file
70 with lockfile.LockFile(self.statefile_path):
71 if os.path.exists(self.statefile_path):
72 with open(self.statefile_path) as statefile:
73 state = json.load(statefile)
74 else:
75 state = {}
76
77 state[sys.prefix] = {
78 "last_check": current_time.strftime(SELFCHECK_DATE_FMT),
79 "pypi_version": pypi_version,
80 }
81
82 with open(self.statefile_path, "w") as statefile:
83 json.dump(state, statefile, sort_keys=True,
84 separators=(",", ":"))
85
86
87def load_selfcheck_statefile():
88 if running_under_virtualenv():
89 return VirtualenvSelfCheckState()
90 else:
91 return GlobalSelfCheckState()
92
93
94def pip_version_check(session, options):
95 """Check for an update for pip.
96
97 Limit the frequency of checks to once per week. State is stored either in
98 the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix
99 of the pip script path.
100 """
101 installed_version = get_installed_version("pip")
102 if not installed_version:
103 return
104
105 pip_version = packaging_version.parse(installed_version)
106 pypi_version = None
107
108 try:
109 state = load_selfcheck_statefile()
110
111 current_time = datetime.datetime.utcnow()
112 # Determine if we need to refresh the state
113 if "last_check" in state.state and "pypi_version" in state.state:
114 last_check = datetime.datetime.strptime(
115 state.state["last_check"],
116 SELFCHECK_DATE_FMT
117 )
118 if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60:
119 pypi_version = state.state["pypi_version"]
120
121 # Refresh the version if we need to or just see if we need to warn
122 if pypi_version is None:
123 # Lets use PackageFinder to see what the latest pip version is
124 finder = PackageFinder(
125 find_links=options.find_links,
126 index_urls=[options.index_url] + options.extra_index_urls,
127 allow_all_prereleases=False, # Explicitly set to False
128 trusted_hosts=options.trusted_hosts,
129 process_dependency_links=options.process_dependency_links,
130 session=session,
131 )
132 all_candidates = finder.find_all_candidates("pip")
133 if not all_candidates:
134 return
135 pypi_version = str(
136 max(all_candidates, key=lambda c: c.version).version
137 )
138
139 # save that we've performed a check
140 state.save(pypi_version, current_time)
141
142 remote_version = packaging_version.parse(pypi_version)
143
144 # Determine if our pypi_version is older
145 if (pip_version < remote_version and
146 pip_version.base_version != remote_version.base_version):
147 # Advise "python -m pip" on Windows to avoid issues
148 # with overwriting pip.exe.
149 if WINDOWS:
150 pip_cmd = "python -m pip"
151 else:
152 pip_cmd = "pip"
153 logger.warning(
154 "You are using pip version %s, however version %s is "
155 "available.\nYou should consider upgrading via the "
156 "'%s install --upgrade pip' command.",
157 pip_version, pypi_version, pip_cmd
158 )
159 except Exception:
160 logger.debug(
161 "There was an error checking the latest version of pip",
162 exc_info=True,
163 )
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/packaging.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/packaging.py
deleted file mode 100644
index d523953..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/packaging.py
+++ /dev/null
@@ -1,70 +0,0 @@
1from __future__ import absolute_import
2
3import logging
4import sys
5from email.parser import FeedParser # type: ignore
6
7from pip._vendor import pkg_resources
8from pip._vendor.packaging import specifiers, version
9
10from pip._internal import exceptions
11
12logger = logging.getLogger(__name__)
13
14
15def check_requires_python(requires_python):
16 """
17 Check if the python version in use match the `requires_python` specifier.
18
19 Returns `True` if the version of python in use matches the requirement.
20 Returns `False` if the version of python in use does not matches the
21 requirement.
22
23 Raises an InvalidSpecifier if `requires_python` have an invalid format.
24 """
25 if requires_python is None:
26 # The package provides no information
27 return True
28 requires_python_specifier = specifiers.SpecifierSet(requires_python)
29
30 # We only use major.minor.micro
31 python_version = version.parse('.'.join(map(str, sys.version_info[:3])))
32 return python_version in requires_python_specifier
33
34
35def get_metadata(dist):
36 if (isinstance(dist, pkg_resources.DistInfoDistribution) and
37 dist.has_metadata('METADATA')):
38 return dist.get_metadata('METADATA')
39 elif dist.has_metadata('PKG-INFO'):
40 return dist.get_metadata('PKG-INFO')
41
42
43def check_dist_requires_python(dist):
44 metadata = get_metadata(dist)
45 feed_parser = FeedParser()
46 feed_parser.feed(metadata)
47 pkg_info_dict = feed_parser.close()
48 requires_python = pkg_info_dict.get('Requires-Python')
49 try:
50 if not check_requires_python(requires_python):
51 raise exceptions.UnsupportedPythonVersion(
52 "%s requires Python '%s' but the running Python is %s" % (
53 dist.project_name,
54 requires_python,
55 '.'.join(map(str, sys.version_info[:3])),)
56 )
57 except specifiers.InvalidSpecifier as e:
58 logger.warning(
59 "Package %s has an invalid Requires-Python entry %s - %s",
60 dist.project_name, requires_python, e,
61 )
62 return
63
64
65def get_installer(dist):
66 if dist.has_metadata('INSTALLER'):
67 for line in dist.get_metadata_lines('INSTALLER'):
68 if line.strip():
69 return line.strip()
70 return ''
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/setuptools_build.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/setuptools_build.py
deleted file mode 100644
index 9d32174..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/setuptools_build.py
+++ /dev/null
@@ -1,8 +0,0 @@
1# Shim to wrap setup.py invocation with setuptools
2SETUPTOOLS_SHIM = (
3 "import setuptools, tokenize;__file__=%r;"
4 "f=getattr(tokenize, 'open', open)(__file__);"
5 "code=f.read().replace('\\r\\n', '\\n');"
6 "f.close();"
7 "exec(compile(code, __file__, 'exec'))"
8)
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/temp_dir.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/temp_dir.py
deleted file mode 100644
index 25bc0d9..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/temp_dir.py
+++ /dev/null
@@ -1,82 +0,0 @@
1from __future__ import absolute_import
2
3import logging
4import os.path
5import tempfile
6
7from pip._internal.utils.misc import rmtree
8
9logger = logging.getLogger(__name__)
10
11
12class TempDirectory(object):
13 """Helper class that owns and cleans up a temporary directory.
14
15 This class can be used as a context manager or as an OO representation of a
16 temporary directory.
17
18 Attributes:
19 path
20 Location to the created temporary directory or None
21 delete
22 Whether the directory should be deleted when exiting
23 (when used as a contextmanager)
24
25 Methods:
26 create()
27 Creates a temporary directory and stores its path in the path
28 attribute.
29 cleanup()
30 Deletes the temporary directory and sets path attribute to None
31
32 When used as a context manager, a temporary directory is created on
33 entering the context and, if the delete attribute is True, on exiting the
34 context the created directory is deleted.
35 """
36
37 def __init__(self, path=None, delete=None, kind="temp"):
38 super(TempDirectory, self).__init__()
39
40 if path is None and delete is None:
41 # If we were not given an explicit directory, and we were not given
42 # an explicit delete option, then we'll default to deleting.
43 delete = True
44
45 self.path = path
46 self.delete = delete
47 self.kind = kind
48
49 def __repr__(self):
50 return "<{} {!r}>".format(self.__class__.__name__, self.path)
51
52 def __enter__(self):
53 self.create()
54 return self
55
56 def __exit__(self, exc, value, tb):
57 if self.delete:
58 self.cleanup()
59
60 def create(self):
61 """Create a temporary directory and store it's path in self.path
62 """
63 if self.path is not None:
64 logger.debug(
65 "Skipped creation of temporary directory: {}".format(self.path)
66 )
67 return
68 # We realpath here because some systems have their default tmpdir
69 # symlinked to another directory. This tends to confuse build
70 # scripts, so we canonicalize the path by traversing potential
71 # symlinks here.
72 self.path = os.path.realpath(
73 tempfile.mkdtemp(prefix="pip-{}-".format(self.kind))
74 )
75 logger.debug("Created temporary directory: {}".format(self.path))
76
77 def cleanup(self):
78 """Remove the temporary directory created and reset state
79 """
80 if self.path is not None and os.path.exists(self.path):
81 rmtree(self.path)
82 self.path = None
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/typing.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/typing.py
deleted file mode 100644
index 4e25ae6..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/typing.py
+++ /dev/null
@@ -1,29 +0,0 @@
1"""For neatly implementing static typing in pip.
2
3`mypy` - the static type analysis tool we use - uses the `typing` module, which
4provides core functionality fundamental to mypy's functioning.
5
6Generally, `typing` would be imported at runtime and used in that fashion -
7it acts as a no-op at runtime and does not have any run-time overhead by
8design.
9
10As it turns out, `typing` is not vendorable - it uses separate sources for
11Python 2/Python 3. Thus, this codebase can not expect it to be present.
12To work around this, mypy allows the typing import to be behind a False-y
13optional to prevent it from running at runtime and type-comments can be used
14to remove the need for the types to be accessible directly during runtime.
15
16This module provides the False-y guard in a nicely named fashion so that a
17curious maintainer can reach here to read this.
18
19In pip, all static-typing related imports should be guarded as follows:
20
21 from pip.utils.typing import MYPY_CHECK_RUNNING
22
23 if MYPY_CHECK_RUNNING:
24 from typing import ...
25
26Ref: https://github.com/python/mypy/issues/3216
27"""
28
29MYPY_CHECK_RUNNING = False
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/ui.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/ui.py
deleted file mode 100644
index d97ea36..0000000
--- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/utils/ui.py
+++ /dev/null
@@ -1,421 +0,0 @@
1from __future__ import absolute_import, division
2
3import contextlib
4import itertools
5import logging
6import sys
7import time
8from signal import SIGINT, default_int_handler, signal
9
10from pip._vendor import six
11from pip._vendor.progress.bar import (
12 Bar, ChargingBar, FillingCirclesBar, FillingSquaresBar, IncrementalBar,
13 ShadyBar,
14)
15from pip._vendor.progress.helpers import HIDE_CURSOR, SHOW_CURSOR, WritelnMixin
16from pip._vendor.progress.spinner import Spinner
17
18from pip._internal.compat import WINDOWS
19from pip._internal.utils.logging import get_indentation
20from pip._internal.utils.misc import format_size
21from pip._internal.utils.typing import MYPY_CHECK_RUNNING
22
23if MYPY_CHECK_RUNNING:
24 from typing import Any
25
26try:
27 from pip._vendor import colorama
28# Lots of different errors can come from this, including SystemError and
29# ImportError.
30except Exception:
31 colorama = None
32
33logger = logging.getLogger(__name__)
34
35
36def _select_progress_class(preferred, fallback):
37 encoding = getattr(preferred.file, "encoding", None)
38
39 # If we don't know what encoding this file is in, then we'll just assume
40 # that it doesn't support unicode and use the ASCII bar.
41 if not encoding:
42 return fallback
43
44 # Collect all of the possible characters we want to use with the preferred
45 # bar.
46 characters = [
47 getattr(preferred, "empty_fill", six.text_type()),
48 getattr(preferred, "fill", six.text_type()),
49 ]
50 characters += list(getattr(preferred, "phases", []))
51
52 # Try to decode the characters we're using for the bar using the encoding
53 # of the given file, if this works then we'll assume that we can use the
54 # fancier bar and if not we'll fall back to the plaintext bar.
55 try:
56 six.text_type().join(characters).encode(encoding)
57 except UnicodeEncodeError:
58 return fallback
59 else:
60 return preferred
61
62
63_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any
64
65
66class InterruptibleMixin(object):
67 """
68 Helper to ensure that self.finish() gets called on keyboard interrupt.
69
70 This allows downloads to be interrupted without leaving temporary state
71 (like hidden cursors) behind.
72
73 This class is similar to the progress library's existing SigIntMixin
74 helper, but as of version 1.2, that helper has the following problems:
75
76 1. It calls sys.exit().
77 2. It discards the existing SIGINT handler completely.
78 3. It leaves its own handler in place even after an uninterrupted finish,
79 which will have unexpected delayed effects if the user triggers an
80 unrelated keyboard interrupt some time after a progress-displaying
81 download has already completed, for example.
82 """
83
84 def __init__(self, *args, **kwargs):
85 """
86 Save the original SIGINT handler for later.
87 """
88 super(InterruptibleMixin, self).__init__(*args, **kwargs)
89
90 self.original_handler = signal(SIGINT, self.handle_sigint)
91
92 # If signal() returns None, the previous handler was not installed from
93 # Python, and we cannot restore it. This probably should not happen,
94 # but if it does, we must restore something sensible instead, at least.
95 # The least bad option should be Python's default SIGINT handler, which
96 # just raises KeyboardInterrupt.
97 if self.original_handler is None:
98 self.original_handler = default_int_handler
99
100 def finish(self):
101 """
102 Restore the original SIGINT handler after finishing.
103
104 This should happen regardless of whether the progress display finishes
105 normally, or gets interrupted.
106 """
107 super(InterruptibleMixin, self).finish()
108 signal(SIGINT, self.original_handler)
109
110 def handle_sigint(self, signum, frame):
111 """
112 Call self.finish() before delegating to the original SIGINT handler.
113
114 This handler should only be in place while the progress display is
115 active.
116 """
117 self.finish()
118 self.original_handler(signum, frame)
119
120
121class SilentBar(Bar):
122
123 def update(self):
124 pass
125
126
127class BlueEmojiBar(IncrementalBar):
128
129 suffix = "%(percent)d%%"
130 bar_prefix = " "
131 bar_suffix = " "
132 phases = (u"\U0001F539", u"\U0001F537", u"\U0001F535") # type: Any
133
134
135class DownloadProgressMixin(object):
136
137 def __init__(self, *args, **kwargs):
138 super(DownloadProgressMixin, self).__init__(*args, **kwargs)
139 self.message = (" " * (get_indentation() + 2)) + self.message
140
141 @property
142 def downloaded(self):
143 return format_size(self.index)
144
145 @property
146 def download_speed(self):
147 # Avoid zero division errors...
148 if self.avg == 0.0:
149 return "..."
150 return format_size(1 / self.avg) + "/s"
151
152 @property
153 def pretty_eta(self):
154 if self.eta:
155 return "eta %s" % self.eta_td
156 return ""
157
158 def iter(self, it, n=1):
159 for x in it:
160 yield x
161 self.next(n)
162 self.finish()
163
164
165class WindowsMixin(object):
166
167 def __init__(self, *args, **kwargs):
168 # The Windows terminal does not support the hide/show cursor ANSI codes
169 # even with colorama. So we'll ensure that hide_cursor is False on
170 # Windows.
171 # This call neds to go before the super() call, so that hide_cursor
172 # is set in time. The base progress bar class writes the "hide cursor"
173 # code to the terminal in its init, so if we don't set this soon
174 # enough, we get a "hide" with no corresponding "show"...
175 if WINDOWS and self.hide_cursor:
176 self.hide_cursor = False
177
178 super(WindowsMixin, self).__init__(*args, **kwargs)
179
180 # Check if we are running on Windows and we have the colorama module,
181 # if we do then wrap our file with it.
182 if WINDOWS and colorama:
183 self.file = colorama.AnsiToWin32(self.file)
184 # The progress code expects to be able to call self.file.isatty()
185 # but the colorama.AnsiToWin32() object doesn't have that, so we'll
186 # add it.
187 self.file.isatty = lambda: self.file.wrapped.isatty()
188 # The progress code expects to be able to call self.file.flush()
189 # but the colorama.AnsiToWin32() object doesn't have that, so we'll
190 # add it.
191 self.file.flush = lambda: self.file.wrapped.flush()
192
193
194class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin,
195 DownloadProgressMixin):
196
197 file = sys.stdout
198 message = "%(percent)d%%"
199 suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s"
200
201# NOTE: The "type: ignore" comments on the following classes are there to
202# work around https://github.com/python/typing/issues/241
203
204
205class DefaultDownloadProgressBar(BaseDownloadProgressBar,
206 _BaseBar): # type: ignore
207 pass
208
209
210class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): # type: ignore
211 pass
212
213
214class DownloadIncrementalBar(BaseDownloadProgressBar, # type: ignore
215 IncrementalBar):
216 pass
217
218
219class DownloadChargingBar(BaseDownloadProgressBar, # type: ignore
220 ChargingBar):
221 pass
222
223
224class DownloadShadyBar(BaseDownloadProgressBar, ShadyBar): # type: ignore
225 pass
226
227
228class DownloadFillingSquaresBar(BaseDownloadProgressBar, # type: ignore
229 FillingSquaresBar):
230 pass
231
232
233class DownloadFillingCirclesBar(BaseDownloadProgressBar, # type: ignore
234 FillingCirclesBar):
235 pass
236
237
238class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, # type: ignore
239 BlueEmojiBar):
240 pass
241
242
243class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin,
244 DownloadProgressMixin, WritelnMixin, Spinner):
245
246 file = sys.stdout
247 suffix = "%(downloaded)s %(download_speed)s"
248
249 def next_phase(self):
250 if not hasattr(self, "_phaser"):
251 self._phaser = itertools.cycle(self.phases)
252 return next(self._phaser)
253
254 def update(self):
255 message = self.message % self
256 phase = self.next_phase()
257 suffix = self.suffix % self
258 line = ''.join([
259 message,
260 " " if message else "",
261 phase,
262 " " if suffix else "",
263 suffix,
264 ])
265
266 self.writeln(line)
267
268
269BAR_TYPES = {
270 "off": (DownloadSilentBar, DownloadSilentBar),
271 "on": (DefaultDownloadProgressBar, DownloadProgressSpinner),
272 "ascii": (DownloadIncrementalBar, DownloadProgressSpinner),
273 "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner),
274 "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner)
275}
276
277
278def DownloadProgressProvider(progress_bar, max=None):
279 if max is None or max == 0:
280 return BAR_TYPES[progress_bar][1]().iter
281 else:
282 return BAR_TYPES[progress_bar][0](max=max).iter
283
284
285################################################################
286# Generic "something is happening" spinners
287#
288# We don't even try using progress.spinner.Spinner here because it's actually
289# simpler to reimplement from scratch than to coerce their code into doing
290# what we need.
291################################################################
292
293@contextlib.contextmanager
294def hidden_cursor(file):
295 # The Windows terminal does not support the hide/show cursor ANSI codes,
296 # even via colorama. So don't even try.
297 if WINDOWS:
298 yield
299 # We don't want to clutter the output with control characters if we're
300 # writing to a file, or if the user is running with --quiet.
301 # See https://github.com/pypa/pip/issues/3418
302 elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO:
303 yield
304 else:
305 file.write(HIDE_CURSOR)
306 try:
307 yield
308 finally:
309 file.write(SHOW_CURSOR)
310
311
312class RateLimiter(object):
313 def __init__(self, min_update_interval_seconds):
314 self._min_update_interval_seconds = min_update_interval_seconds
315 self._last_update = 0
316
317 def ready(self):
318 now = time.time()
319 delta = now - self._last_update
320 return delta >= self._min_update_interval_seconds
321
322 def reset(self):
323 self._last_update = time.time()
324
325
326class InteractiveSpinner(object):
327 def __init__(self, message, file=None, spin_chars="-\\|/",
328 # Empirically, 8 updates/second looks nice
329 min_update_interval_seconds=0.125):
330 self._message = message
331 if file is None:
332 file = sys.stdout
333 self._file = file
334 self._rate_limiter = RateLimiter(min_update_interval_seconds)
335 self._finished = False
336
337 self._spin_cycle = itertools.cycle(spin_chars)
338
339 self._file.write(" " * get_indentation() + self._message + " ... ")
340 self._width = 0
341
342 def _write(self, status):
343 assert not self._finished
344 # Erase what we wrote before by backspacing to the beginning, writing
345 # spaces to overwrite the old text, and then backspacing again
346 backup = "\b" * self._width
347 self._file.write(backup + " " * self._width + backup)
348 # Now we have a blank slate to add our status
349 self._file.write(status)
350 self._width = len(status)
351 self._file.flush()
352 self._rate_limiter.reset()
353
354 def spin(self):
355 if self._finished:
356 return
357 if not self._rate_limiter.ready():
358 return
359 self._write(next(self._spin_cycle))
360
361 def finish(self, final_status):
362 if self._finished:
363 return
364 self._write(final_status)
365 self._file.write("\n")
366 self._file.flush()
367 self._finished = True
368
369
370# Used for dumb terminals, non-interactive installs (no tty), etc.
371# We still print updates occasionally (once every 60 seconds by default) to
372# act as a keep-alive for systems like Travis-CI that take lack-of-output as
373# an indication that a task has frozen.
374class NonInteractiveSpinner(object):
375 def __init__(self, message, min_update_interval_seconds=60):
376 self._message = message
377 self._finished = False
378 self._rate_limiter = RateLimiter(min_update_interval_seconds)
379 self._update("started")
380
381 def _update(self, status):
382 assert not self._finished
383 self._rate_limiter.reset()
384 logger.info("%s: %s", self._message, status)
385
386 def spin(self):
387 if self._finished:
388 return
389 if not self._rate_limiter.ready():
390 return
391 self._update("still running...")
392
393 def finish(self, final_status):
394 if self._finished:
395 return
396 self._update("finished with status '%s'" % (final_status,))
397 self._finished = True
398
399
400@contextlib.contextmanager
401def open_spinner(message):
402 # Interactive spinner goes directly to sys.stdout rather than being routed
403 # through the logging system, but it acts like it has level INFO,
404 # i.e. it's only displayed if we're at level INFO or better.
405 # Non-interactive spinner goes through the logging system, so it is always
406 # in sync with logging configuration.
407 if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO:
408 spinner = InteractiveSpinner(message)
409 else:
410 spinner = NonInteractiveSpinner(message)
411 try:
412 with hidden_cursor(sys.stdout):
413 yield spinner
414 except KeyboardInterrupt:
415 spinner.finish("canceled")
416 raise
417 except Exception:
418 spinner.finish("error")
419 raise
420 else:
421 spinner.finish("done")