From cd979694b72b8f7e7b40fcdc62691e3c380f0778 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Tue, 30 Aug 2022 08:54:04 -0400 Subject: [PATCH 1/3] Vendor in requirementslib==2.0.1 and vistir==0.6.1 --- pipenv/vendor/requirementslib/__init__.py | 2 +- .../vendor/requirementslib/models/metadata.py | 10 +- .../requirementslib/models/requirements.py | 6 +- pipenv/vendor/requirementslib/models/url.py | 9 +- pipenv/vendor/vendor.txt | 4 +- pipenv/vendor/vistir/__init__.py | 2 +- pipenv/vendor/vistir/_winconsole.py | 49 +--- pipenv/vendor/vistir/backports/__init__.py | 8 - pipenv/vendor/vistir/backports/functools.py | 84 ------ .../vistir/backports/surrogateescape.py | 196 -------------- pipenv/vendor/vistir/backports/tempfile.py | 234 ----------------- pipenv/vendor/vistir/cmdparse.py | 4 +- pipenv/vendor/vistir/compat.py | 247 ++++-------------- pipenv/vendor/vistir/contextmanagers.py | 14 +- pipenv/vendor/vistir/misc.py | 131 ++++------ pipenv/vendor/vistir/path.py | 68 +---- pipenv/vendor/vistir/spin.py | 9 +- pipenv/vendor/vistir/termcolors.py | 3 +- 18 files changed, 152 insertions(+), 928 deletions(-) delete mode 100644 pipenv/vendor/vistir/backports/__init__.py delete mode 100644 pipenv/vendor/vistir/backports/functools.py delete mode 100644 pipenv/vendor/vistir/backports/surrogateescape.py delete mode 100644 pipenv/vendor/vistir/backports/tempfile.py diff --git a/pipenv/vendor/requirementslib/__init__.py b/pipenv/vendor/requirementslib/__init__.py index a12704956a..bab419ae19 100644 --- a/pipenv/vendor/requirementslib/__init__.py +++ b/pipenv/vendor/requirementslib/__init__.py @@ -5,7 +5,7 @@ from .models.pipfile import Pipfile from .models.requirements import Requirement -__version__ = "2.0.0" +__version__ = "2.0.1" logger = logging.getLogger(__name__) diff --git a/pipenv/vendor/requirementslib/models/metadata.py b/pipenv/vendor/requirementslib/models/metadata.py index 39ffb76c22..d008d15020 100644 --- a/pipenv/vendor/requirementslib/models/metadata.py +++ b/pipenv/vendor/requirementslib/models/metadata.py @@ -12,7 +12,6 @@ from typing import Sequence import pipenv.vendor.attr as attr -import dateutil.parser import distlib.metadata import distlib.wheel import pipenv.patched.pip._vendor.requests as requests @@ -501,12 +500,17 @@ class ReleaseUrl(object): #: The upload timestamp from the package upload_time = attr.ib( type=datetime.datetime, - converter=instance_check_converter(datetime.datetime, dateutil.parser.parse), # type: ignore + converter=instance_check_converter( + datetime.datetime, datetime.datetime.fromisoformat + ), # type: ignore ) #: The ISO8601 formatted upload timestamp of the package upload_time_iso_8601 = attr.ib( type=datetime.datetime, - converter=instance_check_converter(datetime.datetime, dateutil.parser.parse), # type: ignore + converter=instance_check_converter( + datetime.datetime, + lambda t_str: datetime.datetime.strptime(t_str, "%Y-%m-%dT%H:%M:%S.%fZ"), + ), # type: ignore ) #: The size in bytes of the package size = attr.ib(type=int) diff --git a/pipenv/vendor/requirementslib/models/requirements.py b/pipenv/vendor/requirementslib/models/requirements.py index bfc916af6a..b075285472 100644 --- a/pipenv/vendor/requirementslib/models/requirements.py +++ b/pipenv/vendor/requirementslib/models/requirements.py @@ -2525,7 +2525,11 @@ def get_line_instance(self): else: line_parts.append(self.req.line_part) if not self.is_vcs and not self.vcs and self.extras_as_pip: - if self.is_file_or_url and not local_editable: + if ( + self.is_file_or_url + and not local_editable + and not self.req.get_uri().startswith("file://") + ): line_parts.append(f"#egg={self.extras_as_pip}") else: line_parts.append(self.extras_as_pip) diff --git a/pipenv/vendor/requirementslib/models/url.py b/pipenv/vendor/requirementslib/models/url.py index a3c711f634..a35dd4fb92 100644 --- a/pipenv/vendor/requirementslib/models/url.py +++ b/pipenv/vendor/requirementslib/models/url.py @@ -6,7 +6,6 @@ from urllib.parse import unquote_plus import pipenv.vendor.attr as attr -from pipenv.vendor.orderedmultidict import omdict from pipenv.patched.pip._internal.models.link import Link from pipenv.patched.pip._internal.req.constructors import _strip_extras from pipenv.patched.pip._vendor.urllib3.util import parse_url as urllib3_parse @@ -87,8 +86,8 @@ class URI(object): username = attr.ib(default="", type=str) #: Password parsed from `user:password@hostname` password = attr.ib(default="", type=str, repr=False) - #: An orderedmultidict representing query fragments - query_dict = attr.ib(factory=omdict, type=omdict) + #: A dictionary representing query fragments + query_dict = attr.ib(factory=dict, type=dict) #: The name of the specified package in case it is a VCS URI with an egg fragment name = attr.ib(default="", type=str) #: Any extras requested from the requirement @@ -105,7 +104,7 @@ class URI(object): def _parse_query(self): # type: () -> URI query = self.query if self.query is not None else "" - query_dict = omdict() + query_dict = dict() queries = query.split("&") query_items = [] subdirectory = self.subdirectory if self.subdirectory else None @@ -116,7 +115,7 @@ def _parse_query(self): subdirectory = val else: query_items.append((key, val)) - query_dict.load(query_items) + query_dict.update(query_items) return attr.evolve( self, query_dict=query_dict, subdirectory=subdirectory, query=query ) diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index bbdbc7500f..1ee6ade784 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -20,13 +20,13 @@ pyparsing==3.0.9 python-dateutil==2.8.2 python-dotenv==0.19.0 pythonfinder==1.3.1 -requirementslib==2.0.0 +requirementslib==2.0.1 shellingham==1.4.0 six==1.16.0 termcolor==1.1.0 toml==0.10.2 tomli==1.1.0 tomlkit==0.9.2 -vistir==0.5.6 +vistir==0.6.1 wheel==0.36.2 yaspin==2.0.0 diff --git a/pipenv/vendor/vistir/__init__.py b/pipenv/vendor/vistir/__init__.py index 9bc1b9585b..e715298b74 100644 --- a/pipenv/vendor/vistir/__init__.py +++ b/pipenv/vendor/vistir/__init__.py @@ -36,7 +36,7 @@ from .path import create_tracked_tempdir, create_tracked_tempfile, mkdir_p, rmtree from .spin import create_spinner -__version__ = "0.5.6" +__version__ = "0.6.1" __all__ = [ diff --git a/pipenv/vendor/vistir/_winconsole.py b/pipenv/vendor/vistir/_winconsole.py index cb5e6d27ca..6ebc89bc0b 100644 --- a/pipenv/vendor/vistir/_winconsole.py +++ b/pipenv/vendor/vistir/_winconsole.py @@ -64,7 +64,6 @@ from itertools import count import msvcrt -from pipenv.vendor.six import PY2, text_type from .compat import IS_TYPE_CHECKING from .misc import StreamWrapper, run, to_text @@ -136,9 +135,6 @@ class Py_buffer(Structure): ("internal", c_void_p), ] - if PY2: - _fields_.insert(-1, ("smalltable", c_ssize_t * 2)) - # XXX: This was added for the use of cursors class CONSOLE_CURSOR_INFO(Structure): @@ -253,7 +249,7 @@ def fileno(self): return self.buffer.fileno def write(self, x): - if isinstance(x, text_type): + if isinstance(x, str): return self._text_stream.write(x) try: self.flush() @@ -306,13 +302,6 @@ def write(self, text): _wrapped_std_streams = set() -def _wrap_std_stream(name): - # Python 2 & Windows 7 and below - if PY2 and sys.getwindowsversion()[:2] <= (6, 1) and name not in _wrapped_std_streams: - setattr(sys, name, WindowsChunkedWriter(getattr(sys, name))) - _wrapped_std_streams.add(name) - - def _get_text_stdin(buffer_stream): text_stream = StreamWrapper( io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), @@ -343,35 +332,6 @@ def _get_text_stderr(buffer_stream): return ConsoleStream(text_stream, buffer_stream) -if PY2: - - def _hash_py_argv(): - return zlib.crc32("\x00".join(sys.argv[1:])) - - _initial_argv_hash = _hash_py_argv() - - def _get_windows_argv(): - argc = c_int(0) - argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) - try: - argv = [argv_unicode[i] for i in range(0, argc.value)] - finally: - LocalFree(argv_unicode) - del argv_unicode - - if not hasattr(sys, "frozen"): - argv = argv[1:] - while len(argv) > 0: - arg = argv[0] - if not arg.startswith("-") or arg == "-": - break - argv = argv[1:] - if arg.startswith(("-c", "-m")): - break - - return argv[1:] - - _stream_factories = {0: _get_text_stdin, 1: _get_text_stdout, 2: _get_text_stderr} @@ -387,10 +347,9 @@ def _get_windows_console_stream(f, encoding, errors): return f func = _stream_factories.get(f.fileno()) if func is not None: - if not PY2: - f = getattr(f, "buffer", None) - if f is None: - return None + f = getattr(f, "buffer", None) + if f is None: + return None else: # If we are on Python 2 we need to set the stream that we # deal with to binary mode as otherwise the exercise if a diff --git a/pipenv/vendor/vistir/backports/__init__.py b/pipenv/vendor/vistir/backports/__init__.py deleted file mode 100644 index b5ed656229..0000000000 --- a/pipenv/vendor/vistir/backports/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from .functools import partialmethod -from .surrogateescape import register_surrogateescape -from .tempfile import NamedTemporaryFile - -__all__ = ["NamedTemporaryFile", "partialmethod", "register_surrogateescape"] diff --git a/pipenv/vendor/vistir/backports/functools.py b/pipenv/vendor/vistir/backports/functools.py deleted file mode 100644 index 5d98f41acc..0000000000 --- a/pipenv/vendor/vistir/backports/functools.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from functools import partial - -__all__ = ["partialmethod"] - - -class partialmethod(object): - """Method descriptor with partial application of the given arguments - and keywords. - Supports wrapping existing descriptors and handles non-descriptor - callables as instance methods. - """ - - def __init__(self, func, *args, **keywords): - if not callable(func) and not hasattr(func, "__get__"): - raise TypeError("{!r} is not callable or a descriptor".format(func)) - - # func could be a descriptor like classmethod which isn't callable, - # so we can't inherit from partial (it verifies func is callable) - if isinstance(func, partialmethod): - # flattening is mandatory in order to place cls/self before all - # other arguments - # it's also more efficient since only one function will be called - self.func = func.func - self.args = func.args + args - self.keywords = func.keywords.copy() - self.keywords.update(keywords) - else: - self.func = func - self.args = args - self.keywords = keywords - - def __repr__(self): - args = ", ".join(map(repr, self.args)) - keywords = ", ".join("{}={!r}".format(k, v) for k, v in self.keywords.items()) - format_string = "{module}.{cls}({func}, {args}, {keywords})" - return format_string.format( - module=self.__class__.__module__, - cls=self.__class__.__qualname__, - func=self.func, - args=args, - keywords=keywords, - ) - - def _make_unbound_method(self): - def _method(*args, **keywords): - call_keywords = self.keywords.copy() - call_keywords.update(keywords) - if len(args) > 1: - cls_or_self, rest = args[0], tuple(args[1:]) - else: - cls_or_self = args[0] - rest = tuple() - call_args = (cls_or_self,) + self.args + tuple(rest) - return self.func(*call_args, **call_keywords) - - _method.__isabstractmethod__ = self.__isabstractmethod__ - _method._partialmethod = self - return _method - - def __get__(self, obj, cls): - get = getattr(self.func, "__get__", None) - result = None - if get is not None: - new_func = get(obj, cls) - if new_func is not self.func: - # Assume __get__ returning something new indicates the - # creation of an appropriate callable - result = partial(new_func, *self.args, **self.keywords) - try: - result.__self__ = new_func.__self__ - except AttributeError: - pass - if result is None: - # If the underlying descriptor didn't do anything, treat this - # like an instance method - result = self._make_unbound_method().__get__(obj, cls) - return result - - @property - def __isabstractmethod__(self): - return getattr(self.func, "__isabstractmethod__", False) diff --git a/pipenv/vendor/vistir/backports/surrogateescape.py b/pipenv/vendor/vistir/backports/surrogateescape.py deleted file mode 100644 index 5897d57349..0000000000 --- a/pipenv/vendor/vistir/backports/surrogateescape.py +++ /dev/null @@ -1,196 +0,0 @@ -""" -This is Victor Stinner's pure-Python implementation of PEP 383: the "surrogateescape" error -handler of Python 3. -Source: misc/python/surrogateescape.py in https://bitbucket.org/haypo/misc -""" - -# This code is released under the Python license and the BSD 2-clause license - -import codecs -import sys - -import pipenv.vendor.six as six - -FS_ERRORS = "surrogateescape" - -# # -- Python 2/3 compatibility ------------------------------------- -# FS_ERRORS = 'my_surrogateescape' - - -def u(text): - if six.PY3: - return text - else: - return text.decode("unicode_escape") - - -def b(data): - if six.PY3: - return data.encode("latin1") - else: - return data - - -if six.PY3: - _unichr = chr - bytes_chr = lambda code: bytes((code,)) -else: - _unichr = unichr # type: ignore - bytes_chr = chr - - -def surrogateescape_handler(exc): - """ - Pure Python implementation of the PEP 383: the "surrogateescape" error - handler of Python 3. Undecodable bytes will be replaced by a Unicode - character U+DCxx on decoding, and these are translated into the - original bytes on encoding. - """ - mystring = exc.object[exc.start : exc.end] - - try: - if isinstance(exc, UnicodeDecodeError): - # mystring is a byte-string in this case - decoded = replace_surrogate_decode(mystring) - elif isinstance(exc, UnicodeEncodeError): - # In the case of u'\udcc3'.encode('ascii', - # 'this_surrogateescape_handler'), both Python 2.x and 3.x raise an - # exception anyway after this function is called, even though I think - # it's doing what it should. It seems that the strict encoder is called - # to encode the unicode string that this function returns ... - decoded = replace_surrogate_encode(mystring) - else: - raise exc - except NotASurrogateError: - raise exc - return (decoded, exc.end) - - -class NotASurrogateError(Exception): - pass - - -def replace_surrogate_encode(mystring): - """ - Returns a (unicode) string, not the more logical bytes, because the codecs - register_error functionality expects this. - """ - decoded = [] - for ch in mystring: - # if utils.PY3: - # code = ch - # else: - code = ord(ch) - - # The following magic comes from Py3.3's Python/codecs.c file: - if not 0xD800 <= code <= 0xDCFF: - # Not a surrogate. Fail with the original exception. - raise NotASurrogateError - # mybytes = [0xe0 | (code >> 12), - # 0x80 | ((code >> 6) & 0x3f), - # 0x80 | (code & 0x3f)] - # Is this a good idea? - if 0xDC00 <= code <= 0xDC7F: - decoded.append(_unichr(code - 0xDC00)) - elif code <= 0xDCFF: - decoded.append(_unichr(code - 0xDC00)) - else: - raise NotASurrogateError - return str().join(decoded) - - -def replace_surrogate_decode(mybytes): - """ - Returns a (unicode) string - """ - decoded = [] - for ch in mybytes: - # We may be parsing newbytes (in which case ch is an int) or a native - # str on Py2 - if isinstance(ch, int): - code = ch - else: - code = ord(ch) - if 0x80 <= code <= 0xFF: - decoded.append(_unichr(0xDC00 + code)) - elif code <= 0x7F: - decoded.append(_unichr(code)) - else: - # # It may be a bad byte - # # Try swallowing it. - # continue - # print("RAISE!") - raise NotASurrogateError - return str().join(decoded) - - -def encodefilename(fn): - if FS_ENCODING == "ascii": - # ASCII encoder of Python 2 expects that the error handler returns a - # Unicode string encodable to ASCII, whereas our surrogateescape error - # handler has to return bytes in 0x80-0xFF range. - encoded = [] - for index, ch in enumerate(fn): - code = ord(ch) - if code < 128: - ch = bytes_chr(code) - elif 0xDC80 <= code <= 0xDCFF: - ch = bytes_chr(code - 0xDC00) - else: - raise UnicodeEncodeError( - FS_ENCODING, fn, index, index + 1, "ordinal not in range(128)" - ) - encoded.append(ch) - return bytes().join(encoded) - elif FS_ENCODING == "utf-8": - # UTF-8 encoder of Python 2 encodes surrogates, so U+DC80-U+DCFF - # doesn't go through our error handler - encoded = [] - for index, ch in enumerate(fn): - code = ord(ch) - if 0xD800 <= code <= 0xDFFF: - if 0xDC80 <= code <= 0xDCFF: - ch = bytes_chr(code - 0xDC00) - encoded.append(ch) - else: - raise UnicodeEncodeError( - FS_ENCODING, fn, index, index + 1, "surrogates not allowed" - ) - else: - ch_utf8 = ch.encode("utf-8") - encoded.append(ch_utf8) - return bytes().join(encoded) - else: - return fn.encode(FS_ENCODING, FS_ERRORS) - - -def decodefilename(fn): - return fn.decode(FS_ENCODING, FS_ERRORS) - - -FS_ENCODING = "ascii" -fn = b("[abc\xff]") -encoded = u("[abc\udcff]") -# FS_ENCODING = 'cp932'; fn = b('[abc\x81\x00]'); encoded = u('[abc\udc81\x00]') -# FS_ENCODING = 'UTF-8'; fn = b('[abc\xff]'); encoded = u('[abc\udcff]') - - -# normalize the filesystem encoding name. -# For example, we expect "utf-8", not "UTF8". -FS_ENCODING = codecs.lookup(FS_ENCODING).name - - -def register_surrogateescape(): - """ - Registers the surrogateescape error handler on Python 2 (only) - """ - if six.PY3: - return - try: - codecs.lookup_error(FS_ERRORS) - except LookupError: - codecs.register_error(FS_ERRORS, surrogateescape_handler) - - -if __name__ == "__main__": - pass diff --git a/pipenv/vendor/vistir/backports/tempfile.py b/pipenv/vendor/vistir/backports/tempfile.py deleted file mode 100644 index 45b8a08652..0000000000 --- a/pipenv/vendor/vistir/backports/tempfile.py +++ /dev/null @@ -1,234 +0,0 @@ -# -*- coding=utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import functools -import io -import os -import sys -from tempfile import _bin_openflags, _mkstemp_inner, gettempdir - -import pipenv.vendor.six as six - -try: - from weakref import finalize -except ImportError: - from backports.weakref import finalize - - -def fs_encode(path): - try: - return os.fsencode(path) - except AttributeError: - from ..compat import fs_encode - - return fs_encode(path) - - -def fs_decode(path): - try: - return os.fsdecode(path) - except AttributeError: - from ..compat import fs_decode - - return fs_decode(path) - - -__all__ = ["finalize", "NamedTemporaryFile"] - - -try: - from tempfile import _infer_return_type -except ImportError: - - def _infer_return_type(*args): - _types = set() - for arg in args: - if isinstance(type(arg), six.string_types): - _types.add(str) - elif isinstance(type(arg), bytes): - _types.add(bytes) - elif arg: - _types.add(type(arg)) - return _types.pop() - - -def _sanitize_params(prefix, suffix, dir): - """Common parameter processing for most APIs in this module.""" - output_type = _infer_return_type(prefix, suffix, dir) - if suffix is None: - suffix = output_type() - if prefix is None: - if output_type is str: - prefix = "tmp" - else: - prefix = os.fsencode("tmp") - if dir is None: - if output_type is str: - dir = gettempdir() - else: - dir = fs_encode(gettempdir()) - return prefix, suffix, dir, output_type - - -class _TemporaryFileCloser: - """A separate object allowing proper closing of a temporary file's - underlying file object, without adding a __del__ method to the - temporary file.""" - - file = None # Set here since __del__ checks it - close_called = False - - def __init__(self, file, name, delete=True): - self.file = file - self.name = name - self.delete = delete - - # NT provides delete-on-close as a primitive, so we don't need - # the wrapper to do anything special. We still use it so that - # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. - if os.name != "nt": - - # Cache the unlinker so we don't get spurious errors at - # shutdown when the module-level "os" is None'd out. Note - # that this must be referenced as self.unlink, because the - # name TemporaryFileWrapper may also get None'd out before - # __del__ is called. - - def close(self, unlink=os.unlink): - if not self.close_called and self.file is not None: - self.close_called = True - try: - self.file.close() - finally: - if self.delete: - unlink(self.name) - - # Need to ensure the file is deleted on __del__ - - def __del__(self): - self.close() - - else: - - def close(self): - if not self.close_called: - self.close_called = True - self.file.close() - - -class _TemporaryFileWrapper: - """Temporary file wrapper - This class provides a wrapper around files opened for - temporary use. In particular, it seeks to automatically - remove the file when it is no longer needed. - """ - - def __init__(self, file, name, delete=True): - self.file = file - self.name = name - self.delete = delete - self._closer = _TemporaryFileCloser(file, name, delete) - - def __getattr__(self, name): - # Attribute lookups are delegated to the underlying file - # and cached for non-numeric results - # (i.e. methods are cached, closed and friends are not) - file = self.__dict__["file"] - a = getattr(file, name) - if hasattr(a, "__call__"): - func = a - - @functools.wraps(func) - def func_wrapper(*args, **kwargs): - return func(*args, **kwargs) - - # Avoid closing the file as long as the wrapper is alive, - # see issue #18879. - func_wrapper._closer = self._closer - a = func_wrapper - if not isinstance(a, int): - setattr(self, name, a) - return a - - # The underlying __enter__ method returns the wrong object - # (self.file) so override it to return the wrapper - - def __enter__(self): - self.file.__enter__() - return self - - # Need to trap __exit__ as well to ensure the file gets - # deleted when used in a with statement - - def __exit__(self, exc, value, tb): - result = self.file.__exit__(exc, value, tb) - self.close() - return result - - def close(self): - """ - Close the temporary file, possibly deleting it. - """ - self._closer.close() - - # iter() doesn't use __getattr__ to find the __iter__ method - - def __iter__(self): - # Don't return iter(self.file), but yield from it to avoid closing - # file as long as it's being used as iterator (see issue #23700). We - # can't use 'yield from' here because iter(file) returns the file - # object itself, which has a close method, and thus the file would get - # closed when the generator is finalized, due to PEP380 semantics. - for line in self.file: - yield line - - -def NamedTemporaryFile( - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - delete=True, - wrapper_class_override=None, -): - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to io.open (default "w+b"). - 'buffering' -- the buffer size argument to io.open (default -1). - 'encoding' -- the encoding argument to io.open (default None) - 'newline' -- the newline argument to io.open (default None) - 'delete' -- whether the file is deleted on close (default True). - The file is created as mkstemp() would do it. - Returns an object with a file-like interface; the name of the file - is accessible as its 'name' attribute. The file will be automatically - deleted when it is closed unless the 'delete' argument is set to False. - """ - prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) - flags = _bin_openflags - # Setting O_TEMPORARY in the flags causes the OS to delete - # the file when it is closed. This is only supported by Windows. - if not wrapper_class_override: - wrapper_class_override = _TemporaryFileWrapper - if os.name == "nt" and delete: - flags |= os.O_TEMPORARY - if sys.version_info < (3, 5): - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - else: - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) - try: - file = io.open(fd, mode, buffering=buffering, newline=newline, encoding=encoding) - if wrapper_class_override is not None: - return type(str("_TempFileWrapper"), (wrapper_class_override, object), {})( - file, name, delete - ) - else: - return _TemporaryFileWrapper(file, name, delete) - - except BaseException: - os.unlink(name) - os.close(fd) - raise diff --git a/pipenv/vendor/vistir/cmdparse.py b/pipenv/vendor/vistir/cmdparse.py index b04274a58a..704133e41a 100644 --- a/pipenv/vendor/vistir/cmdparse.py +++ b/pipenv/vendor/vistir/cmdparse.py @@ -5,8 +5,6 @@ import re import shlex -import pipenv.vendor.six as six - __all__ = ["ScriptEmptyError", "Script"] @@ -33,7 +31,7 @@ def __init__(self, command, args=None): @classmethod def parse(cls, value): - if isinstance(value, six.string_types): + if isinstance(value, str): value = shlex.split(value) if not value: raise ScriptEmptyError(value) diff --git a/pipenv/vendor/vistir/compat.py b/pipenv/vendor/vistir/compat.py index 336f4f7c58..9292e1dd94 100644 --- a/pipenv/vendor/vistir/compat.py +++ b/pipenv/vendor/vistir/compat.py @@ -8,10 +8,6 @@ import warnings from tempfile import mkdtemp -import pipenv.vendor.six as six - -from .backports.tempfile import NamedTemporaryFile as _NamedTemporaryFile - __all__ = [ "Path", "get_terminal_size", @@ -52,140 +48,44 @@ "_fs_decode_errors", ] -if sys.version_info >= (3, 5): # pragma: no cover - from pathlib import Path -else: # pragma: no cover - from pathlib2 import Path - -if sys.version_info >= (3, 4): # pragma: no cover - # Only Python 3.4+ is supported - from functools import lru_cache, partialmethod - from tempfile import NamedTemporaryFile - from shutil import get_terminal_size - from weakref import finalize - from collections.abc import ( - Mapping, - Hashable, - MutableMapping, - Container, - Iterator, - KeysView, - ItemsView, - MappingView, - Iterable, - Set, - Sequence, - Sized, - ValuesView, - MutableSet, - MutableSequence, - Callable, - ) - from os.path import samefile - -else: # pragma: no cover - # Only Python 2.7 is supported - from backports.functools_lru_cache import lru_cache - from backports.shutil_get_terminal_size import get_terminal_size - from .backports.functools import partialmethod # type: ignore - from .backports.surrogateescape import register_surrogateescape - from collections import ( - Mapping, - Hashable, - MutableMapping, - Container, - Iterator, - KeysView, - ItemsView, - MappingView, - Iterable, - Set, - Sequence, - Sized, - ValuesView, - MutableSet, - MutableSequence, - Callable, - ) - - register_surrogateescape() - NamedTemporaryFile = _NamedTemporaryFile - from backports.weakref import finalize # type: ignore - - try: - from os.path import samefile - except ImportError: - - def samestat(s1, s2): - """Test whether two stat buffers reference the same file.""" - return s1.st_ino == s2.st_ino and s1.st_dev == s2.st_dev - - def samefile(f1, f2): - """Test whether two pathnames reference the same actual file or - directory This is determined by the device number and i-node number - and raises an exception if an os.stat() call on either pathname - fails.""" - s1 = os.stat(f1) - s2 = os.stat(f2) - return samestat(s1, s2) - - -try: - # Introduced Python 3.5 - from json import JSONDecodeError -except ImportError: # pragma: no cover - JSONDecodeError = ValueError # type: ignore - -if six.PY2: # pragma: no cover - - from io import BytesIO as StringIO - - class ResourceWarning(Warning): - pass - - class FileNotFoundError(IOError): - """No such file or directory.""" - - def __init__(self, *args, **kwargs): - self.errno = errno.ENOENT - super(FileNotFoundError, self).__init__(*args, **kwargs) - - class PermissionError(OSError): - def __init__(self, *args, **kwargs): - self.errno = errno.EACCES - super(PermissionError, self).__init__(*args, **kwargs) - - class TimeoutError(OSError): - """Timeout expired.""" - - def __init__(self, *args, **kwargs): - self.errno = errno.ETIMEDOUT - super(TimeoutError, self).__init__(*args, **kwargs) - - class IsADirectoryError(OSError): - """The command does not work on directories.""" - - def __init__(self, *args, **kwargs): - self.errno = errno.EISDIR - super(IsADirectoryError, self).__init__(*args, **kwargs) - - class FileExistsError(OSError): - def __init__(self, *args, **kwargs): - self.errno = errno.EEXIST - super(FileExistsError, self).__init__(*args, **kwargs) - - -else: # pragma: no cover - from builtins import ( - ResourceWarning, - FileNotFoundError, - PermissionError, - IsADirectoryError, - FileExistsError, - TimeoutError, - ) - from io import StringIO - +from pathlib import Path + +from functools import lru_cache, partialmethod +from tempfile import NamedTemporaryFile +from shutil import get_terminal_size +from weakref import finalize +from collections.abc import ( + Mapping, + Hashable, + MutableMapping, + Container, + Iterator, + KeysView, + ItemsView, + MappingView, + Iterable, + Set, + Sequence, + Sized, + ValuesView, + MutableSet, + MutableSequence, + Callable, +) +from os.path import samefile + + +from json import JSONDecodeError + +from builtins import ( + ResourceWarning, + FileNotFoundError, + PermissionError, + IsADirectoryError, + FileExistsError, + TimeoutError, +) +from io import StringIO if not sys.warnoptions: warnings.simplefilter("default", ResourceWarning) @@ -269,9 +169,7 @@ def is_bytes(string): :return: Whether the provided string is a bytes type or not :rtype: bool """ - if six.PY3 and isinstance(string, (bytes, memoryview, bytearray)): # noqa - return True - elif six.PY2 and isinstance(string, (buffer, bytearray)): # noqa + if isinstance(string, (bytes, memoryview, bytearray)): # noqa return True return False @@ -294,14 +192,14 @@ def _get_path(path): Returns **None** if there is no string value. """ - if isinstance(path, (six.string_types, bytes)): + if isinstance(path, (str, bytes)): return path path_type = type(path) try: path_repr = path_type.__fspath__(path) except AttributeError: return - if isinstance(path_repr, (six.string_types, bytes)): + if isinstance(path_repr, (str, bytes)): return path_repr return @@ -362,16 +260,6 @@ def _invalid_utf8_indexes(bytes): return skips -# XXX backport: Another helper to support the Python 2 UTF-8 decoding hack. -def _chunks(b, indexes): - i = 0 - for j in indexes: - yield b[i:j] - yield b[j : j + 1] - i = j + 1 - yield b[i:] - - def fs_encode(path): """Encode a filesystem path to the proper filesystem encoding. @@ -382,16 +270,7 @@ def fs_encode(path): path = _get_path(path) if path is None: raise TypeError("expected a valid path to encode") - if isinstance(path, six.text_type): - if six.PY2: - return b"".join( - ( - _byte(ord(c) - 0xDC00) - if 0xDC00 <= ord(c) <= 0xDCFF - else c.encode(_fs_encoding, _fs_encode_errors) - ) - for c in path - ) + if isinstance(path, str): return path.encode(_fs_encoding, _fs_encode_errors) return path @@ -407,40 +286,30 @@ def fs_decode(path): path = _get_path(path) if path is None: raise TypeError("expected a valid path to decode") - if isinstance(path, six.binary_type): + if isinstance(path, bytes): import array indexes = _invalid_utf8_indexes(array.array(str("B"), path)) - if six.PY2: - return "".join( - chunk.decode(_fs_encoding, _fs_decode_errors) - for chunk in _chunks(path, indexes) - ) if indexes and os.name == "nt": return path.decode(_fs_encoding, "surrogateescape") return path.decode(_fs_encoding, _fs_decode_errors) return path -if sys.version_info[0] < 3: # pragma: no cover - _fs_encode_errors = "surrogatepass" if sys.platform == "win32" else "surrogateescape" - _fs_decode_errors = "surrogateescape" - _fs_encoding = "utf-8" -else: # pragma: no cover - _fs_encoding = "utf-8" - _fs_decode_errors = "surrogateescape" - if sys.platform.startswith("win"): - _fs_error_fn = None - _fs_encode_errors = "surrogatepass" - else: - if sys.version_info >= (3, 3): - _fs_encoding = sys.getfilesystemencoding() - if not _fs_encoding: - _fs_encoding = sys.getdefaultencoding() - alt_strategy = "surrogateescape" - _fs_error_fn = getattr(sys, "getfilesystemencodeerrors", None) - _fs_encode_errors = _fs_error_fn() if _fs_error_fn else alt_strategy - _fs_decode_errors = _fs_error_fn() if _fs_error_fn else _fs_decode_errors +_fs_encoding = "utf-8" +_fs_decode_errors = "surrogateescape" +if sys.platform.startswith("win"): + _fs_error_fn = None + _fs_encode_errors = "surrogatepass" +else: + if sys.version_info >= (3, 3): + _fs_encoding = sys.getfilesystemencoding() + if not _fs_encoding: + _fs_encoding = sys.getdefaultencoding() + alt_strategy = "surrogateescape" + _fs_error_fn = getattr(sys, "getfilesystemencodeerrors", None) + _fs_encode_errors = _fs_error_fn() if _fs_error_fn else alt_strategy + _fs_decode_errors = _fs_error_fn() if _fs_error_fn else _fs_decode_errors _byte = chr if sys.version_info < (3,) else lambda i: bytes([i]) @@ -448,6 +317,4 @@ def fs_decode(path): def to_native_string(string): from .misc import to_text, to_bytes - if six.PY2: - return to_bytes(string) return to_text(string) diff --git a/pipenv/vendor/vistir/contextmanagers.py b/pipenv/vendor/vistir/contextmanagers.py index 013dc88e2b..de0d6b5d4f 100644 --- a/pipenv/vendor/vistir/contextmanagers.py +++ b/pipenv/vendor/vistir/contextmanagers.py @@ -5,9 +5,9 @@ import os import stat import sys -from contextlib import closing, contextmanager -import pipenv.vendor.six as six +from contextlib import closing, contextmanager +from urllib import request from .compat import IS_TYPE_CHECKING, NamedTemporaryFile, Path from .path import is_file_url, is_valid_url, path_to_url, url_to_path @@ -29,7 +29,7 @@ ) from types import ModuleType from pipenv.patched.pip._vendor.requests import Session - from pipenv.vendor.six.moves.http_client import HTTPResponse as Urllib_HTTPResponse + from http.client import HTTPResponse as Urllib_HTTPResponse from pipenv.patched.pip._vendor.urllib3.response import HTTPResponse as Urllib3_HTTPResponse from .spin import VistirSpinner, DummySpinner @@ -177,7 +177,7 @@ def spinner( has_yaspin = None try: import pipenv.vendor.yaspin as yaspin - except ImportError: + except (ImportError, ModuleNotFoundError): # noqa has_yaspin = False if not nospin: raise RuntimeError( @@ -318,7 +318,7 @@ def open_file( :raises ValueError: If link points to a local directory. :return: a context manager to the opened file-like object """ - if not isinstance(link, six.string_types): + if not isinstance(link, str): try: link = link.url_without_fragment except AttributeError: @@ -346,7 +346,7 @@ def open_file( else: session = Session() if session is None: - with closing(six.moves.urllib.request.urlopen(link)) as f: + with closing(request.urlopen(link)) as f: yield f else: with session.get(link, headers=headers, stream=stream) as resp: @@ -381,7 +381,7 @@ def replaced_stream(stream_name): """ orig_stream = getattr(sys, stream_name) - new_stream = six.StringIO() + new_stream = io.StringIO() try: setattr(sys, stream_name, new_stream) yield getattr(sys, stream_name) diff --git a/pipenv/vendor/vistir/misc.py b/pipenv/vendor/vistir/misc.py index d5c633e81b..57ba922745 100644 --- a/pipenv/vendor/vistir/misc.py +++ b/pipenv/vendor/vistir/misc.py @@ -16,8 +16,7 @@ from itertools import islice, tee from weakref import WeakKeyDictionary -import pipenv.vendor.six as six -from pipenv.vendor.six.moves.queue import Empty, Queue +from queue import Empty, Queue from .cmdparse import Script from .compat import ( @@ -119,7 +118,7 @@ def unnest(elem): 2347, 2098, 7987, 27599] """ - if isinstance(elem, Iterable) and not isinstance(elem, six.string_types): + if isinstance(elem, Iterable) and not isinstance(elem, str): elem, target = tee(elem, 2) else: target = elem @@ -127,7 +126,7 @@ def unnest(elem): yield target else: for el in target: - if isinstance(el, Iterable) and not isinstance(el, six.string_types): + if isinstance(el, Iterable) and not isinstance(el, str): el, el_copy = tee(el, 2) for sub in unnest(el_copy): yield sub @@ -286,7 +285,7 @@ def stderr_iter(self): def _decode_line(self, line, encoding): # type: (Union[str, bytes], str) -> str - if isinstance(line, six.binary_type): + if isinstance(line, bytes): line = to_text( line.decode(encoding, errors=_fs_decode_errors).encode( "utf-8", errors=_fs_encode_errors @@ -600,18 +599,11 @@ def run( _env["PYTHONUTF8"] = str("1") if env: _env.update(env) - if six.PY2: - _fs_encode = partial(to_bytes, encoding=locale_encoding) - _env = {_fs_encode(k): _fs_encode(v) for k, v in _env.items()} - else: - _env = {k: fs_str(v) for k, v in _env.items()} + + _env = {k: fs_str(v) for k, v in _env.items()} if not spinner_name: spinner_name = "bouncingBar" - if six.PY2: - if isinstance(cmd, six.string_types): - cmd = cmd.encode("utf-8") - elif isinstance(cmd, (list, tuple)): - cmd = [c.encode("utf-8") for c in cmd] + if not isinstance(cmd, Script): cmd = Script.parse(cmd) if block or not return_object: @@ -726,10 +718,10 @@ def to_bytes(string, encoding="utf-8", errors=None): unicode_name = get_canonical_encoding_name("utf-8") if not errors: if get_canonical_encoding_name(encoding) == unicode_name: - if six.PY3 and os.name == "nt": + if os.name == "nt": errors = "surrogatepass" else: - errors = "surrogateescape" if six.PY3 else "ignore" + errors = "surrogateescape" else: errors = "strict" if isinstance(string, bytes): @@ -739,16 +731,13 @@ def to_bytes(string, encoding="utf-8", errors=None): return string.decode(unicode_name).encode(encoding, errors) elif isinstance(string, memoryview): return string.tobytes() - elif not isinstance(string, six.string_types): # pragma: no cover + elif not isinstance(string, str): # pragma: no cover try: - if six.PY3: - return six.text_type(string).encode(encoding, errors) - else: - return bytes(string) + return str(string).encode(encoding, errors) except UnicodeEncodeError: if isinstance(string, Exception): return b" ".join(to_bytes(arg, encoding, errors) for arg in string) - return six.text_type(string).encode(encoding, errors) + return str(string).encode(encoding, errors) else: return string.encode(encoding, errors) @@ -767,25 +756,21 @@ def to_text(string, encoding="utf-8", errors=None): unicode_name = get_canonical_encoding_name("utf-8") if not errors: if get_canonical_encoding_name(encoding) == unicode_name: - if six.PY3 and os.name == "nt": + if os.name == "nt": errors = "surrogatepass" else: - errors = "surrogateescape" if six.PY3 else "ignore" + errors = "surrogateescape" else: errors = "strict" - if issubclass(type(string), six.text_type): + if issubclass(type(string), str): return string try: - if not issubclass(type(string), six.string_types): - if six.PY3: - if isinstance(string, bytes): - string = six.text_type(string, encoding, errors) - else: - string = six.text_type(string) - elif hasattr(string, "__unicode__"): # pragma: no cover - string = six.text_type(string) + if not issubclass(type(string), str): + if isinstance(string, bytes): + string = str(string, encoding, errors) else: - string = six.text_type(bytes(string), encoding, errors) + string = str(string) + else: string = string.decode(encoding, errors) except UnicodeDecodeError: # pragma: no cover @@ -851,10 +836,6 @@ def getpreferredencoding(): # Borrowed from Invoke # (see https://github.com/pyinvoke/invoke/blob/93af29d/invoke/runners.py#L881) _encoding = sys.getdefaultencoding() or locale.getpreferredencoding(False) - if six.PY2 and not sys.platform == "win32": - _default_encoding = locale.getdefaultlocale()[1] - if _default_encoding is not None: - _encoding = _default_encoding return _encoding @@ -883,12 +864,7 @@ def _encode(output, encoding=None, errors=None, translation_map=None): output = output.encode(encoding) except (UnicodeDecodeError, UnicodeEncodeError): if translation_map is not None: - if six.PY2: - output = unicode.translate( # noqa: F821 - to_text(output, encoding=encoding, errors=errors), translation_map - ) - else: - output = output.translate(translation_map) + output = output.translate(translation_map) else: output = to_text(output, encoding=encoding, errors=errors) except AttributeError: @@ -908,7 +884,7 @@ def decode_for_output(output, target_stream=None, translation_map=None): :rtype: str """ - if not isinstance(output, six.string_types): + if not isinstance(output, str): return output encoding = None if target_stream is not None: @@ -956,7 +932,7 @@ def _is_binary_buffer(stream): def _get_binary_buffer(stream): - if six.PY3 and not _is_binary_buffer(stream): + if not _is_binary_buffer(stream): stream = getattr(stream, "buffer", None) if stream is not None and _is_binary_buffer(stream): return stream @@ -999,39 +975,24 @@ def __init__(self, stream, encoding, errors, line_buffering=True, **kwargs): # borrowed from click's implementation of stream wrappers, see # https://github.com/pallets/click/blob/6cafd32/click/_compat.py#L64 - if six.PY2: - - def write(self, x): - if isinstance(x, (str, buffer, bytearray)): # noqa: F821 - try: - self.flush() - except Exception: - pass - # This is modified from the initial implementation to rely on - # our own decoding functionality to preserve unicode strings where - # possible - return self.buffer.write(str(x)) - return io.TextIOWrapper.write(self, x) - else: + def write(self, x): + # try to use backslash and surrogate escape strategies before failing + self._errors = ( + "backslashescape" if self.encoding != "mbcs" else "surrogateescape" + ) + try: + return io.TextIOWrapper.write(self, to_text(x, errors=self._errors)) + except UnicodeDecodeError: + if self._errors != "surrogateescape": + self._errors = "surrogateescape" + else: + self._errors = "replace" + return io.TextIOWrapper.write(self, to_text(x, errors=self._errors)) - def write(self, x): - # try to use backslash and surrogate escape strategies before failing - self._errors = ( - "backslashescape" if self.encoding != "mbcs" else "surrogateescape" - ) - try: - return io.TextIOWrapper.write(self, to_text(x, errors=self._errors)) - except UnicodeDecodeError: - if self._errors != "surrogateescape": - self._errors = "surrogateescape" - else: - self._errors = "replace" - return io.TextIOWrapper.write(self, to_text(x, errors=self._errors)) - - def writelines(self, lines): - for line in lines: - self.write(line) + def writelines(self, lines): + for line in lines: + self.write(line) def __del__(self): try: @@ -1057,8 +1018,6 @@ def read1(self, size): fn = getattr(self._stream, "read1", None) if fn is not None: return fn(size) - if six.PY2: - return self._stream.readline(size) return self._stream.read(size) def readable(self): @@ -1183,14 +1142,12 @@ def get_text_stream(stream="stdout", encoding=None): stream_map = {"stdin": sys.stdin, "stdout": sys.stdout, "stderr": sys.stderr} if os.name == "nt" or sys.platform.startswith("win"): - from ._winconsole import _get_windows_console_stream, _wrap_std_stream + from ._winconsole import _get_windows_console_stream else: _get_windows_console_stream = lambda *args: None # noqa _wrap_std_stream = lambda *args: None # noqa - if six.PY2 and stream != "stdin": - _wrap_std_stream(stream) sys_stream = stream_map[stream] windows_console = _get_windows_console_stream(sys_stream, encoding, None) if windows_console is not None: @@ -1276,14 +1233,14 @@ def echo(text, fg=None, bg=None, style=None, file=None, err=False, color=None): file = _text_stderr() else: file = _text_stdout() - if text and not isinstance(text, (six.string_types, bytes, bytearray)): - text = six.text_type(text) + if text and not isinstance(text, (str, bytes, bytearray)): + text = str(text) text = "" if not text else text - if isinstance(text, six.text_type): + if isinstance(text, str): text += "\n" else: text += b"\n" - if text and six.PY3 and is_bytes(text): + if text and is_bytes(text): buffer = _get_binary_buffer(file) if buffer is not None: file.flush() diff --git a/pipenv/vendor/vistir/path.py b/pipenv/vendor/vistir/path.py index 9978615afe..8e44346dcd 100644 --- a/pipenv/vendor/vistir/path.py +++ b/pipenv/vendor/vistir/path.py @@ -14,11 +14,9 @@ import unicodedata import warnings -import pipenv.vendor.six as six -from pipenv.vendor.six.moves import urllib_parse -from pipenv.vendor.six.moves.urllib import request as urllib_request +from urllib import parse as urllib_parse +from urllib import request as urllib_request -from .backports.tempfile import _TemporaryFileWrapper from .compat import ( IS_TYPE_CHECKING, FileNotFoundError, @@ -27,17 +25,14 @@ ResourceWarning, TemporaryDirectory, _fs_encoding, - _NamedTemporaryFile, + NamedTemporaryFile, finalize, fs_decode, fs_encode, ) # fmt: off -if six.PY3: - from urllib.parse import quote_from_bytes as quote -else: - from urllib import quote +from urllib.parse import quote_from_bytes as quote # fmt: on @@ -58,10 +53,7 @@ Union, ) - if six.PY3: - TPath = os.PathLike - else: - TPath = Union[str, bytes] + TPath = os.PathLike TFunc = Callable[..., Any] __all__ = [ @@ -97,21 +89,17 @@ def unicode_path(path): # type: (TPath) -> Text # Paths are supposed to be represented as unicode here - if six.PY2 and isinstance(path, six.binary_type): - return path.decode(_fs_encoding) return path def native_path(path): # type: (TPath) -> str - if six.PY2 and isinstance(path, six.text_type): - return path.encode(_fs_encoding) return str(path) # once again thank you django... # https://github.com/django/django/blob/fc6b90b/django/utils/_os.py -if six.PY3 or os.name == "nt": +if os.name == "nt": abspathu = os.path.abspath else: @@ -121,7 +109,7 @@ def abspathu(path): the current working directory, thus avoiding a UnicodeDecodeError in join when the cwd has non-ASCII characters.""" if not os.path.isabs(path): - path = os.path.join(os.getcwdu(), path) + path = os.path.join(os.getcwd(), path) return os.path.normpath(path) @@ -167,7 +155,7 @@ def normalize_drive(path): from .misc import to_text if os.name != "nt" or not ( - isinstance(path, six.string_types) or getattr(path, "__fspath__", None) + isinstance(path, str) or getattr(path, "__fspath__", None) ): return path # type: ignore @@ -244,7 +232,7 @@ def is_file_url(url): if not url: return False - if not isinstance(url, six.string_types): + if not isinstance(url, str): try: url = url.url except AttributeError: @@ -338,8 +326,7 @@ def create_tracked_tempfile(*args, **kwargs): The return value is the file object. """ - kwargs["wrapper_class_override"] = _TrackedTempfileWrapper - return _NamedTemporaryFile(*args, **kwargs) + return NamedTemporaryFile(*args, **kwargs) def _find_icacls_exe(): @@ -611,11 +598,9 @@ def get_converted_relative_path(path, relative_to=None): from .misc import to_text, to_bytes # noqa if not relative_to: - relative_to = os.getcwdu() if six.PY2 else os.getcwd() - if six.PY2: - path = to_bytes(path, encoding="utf-8") - else: - path = to_text(path, encoding="utf-8") + relative_to = os.getcwd() + + path = to_text(path, encoding="utf-8") relative_to = to_text(relative_to, encoding="utf-8") start_path = Path(relative_to) try: @@ -645,31 +630,6 @@ def get_converted_relative_path(path, relative_to=None): def safe_expandvars(value): # type: (TPath) -> str """Call os.path.expandvars if value is a string, otherwise do nothing.""" - if isinstance(value, six.string_types): + if isinstance(value, str): return os.path.expandvars(value) return value # type: ignore - - -class _TrackedTempfileWrapper(_TemporaryFileWrapper, object): - def __init__(self, *args, **kwargs): - super(_TrackedTempfileWrapper, self).__init__(*args, **kwargs) - self._finalizer = finalize(self, self.cleanup) - - @classmethod - def _cleanup(cls, fileobj): - try: - fileobj.close() - finally: - os.unlink(fileobj.name) - - def cleanup(self): - if self._finalizer.detach(): - try: - self.close() - finally: - os.unlink(self.name) - else: - try: - self.close() - except OSError: - pass diff --git a/pipenv/vendor/vistir/spin.py b/pipenv/vendor/vistir/spin.py index 2c7c65cf3a..d1e7841823 100644 --- a/pipenv/vendor/vistir/spin.py +++ b/pipenv/vendor/vistir/spin.py @@ -10,7 +10,6 @@ from io import StringIO import pipenv.vendor.colorama as colorama -import pipenv.vendor.six as six from .compat import IS_TYPE_CHECKING, to_native_string from .cursor import hide_cursor, show_cursor @@ -151,7 +150,7 @@ def hide_and_write(self, text, target=None): # type: (str, Optional[str]) -> None if not target: target = self.stdout - if text is None or isinstance(text, six.string_types) and text == "None": + if text is None or isinstance(text, str) and text == "None": pass target.write(decode_output(u"\r", target_stream=target)) self._hide_cursor(target=target) @@ -163,7 +162,7 @@ def write(self, text=None): # type: (Optional[str]) -> None if not self.write_to_stdout: return self.write_err(text) - if text is None or isinstance(text, six.string_types) and text == "None": + if text is None or isinstance(text, str) and text == "None": pass if not self.stdout.closed: stdout = self.stdout @@ -177,7 +176,7 @@ def write(self, text=None): def write_err(self, text=None): # type: (Optional[str]) -> None - if text is None or isinstance(text, six.string_types) and text == "None": + if text is None or isinstance(text, str) and text == "None": pass text = to_text(text) if not self.stderr.closed: @@ -278,7 +277,7 @@ def hide_and_write(self, text, target=None): # type: (str, Optional[str]) -> None if not target: target = self.stdout - if text is None or isinstance(text, six.string_types) and text == u"None": + if text is None or isinstance(text, str) and text == u"None": pass target.write(decode_output(u"\r")) self._hide_cursor(target=target) diff --git a/pipenv/vendor/vistir/termcolors.py b/pipenv/vendor/vistir/termcolors.py index 68f6e03a64..4807e551b3 100644 --- a/pipenv/vendor/vistir/termcolors.py +++ b/pipenv/vendor/vistir/termcolors.py @@ -5,7 +5,6 @@ import re import pipenv.vendor.colorama as colorama -import pipenv.vendor.six as six from .compat import to_native_string @@ -79,7 +78,7 @@ def colorize(text, fg=None, bg=None, attrs=None): style = "NORMAL" if attrs is not None and not isinstance(attrs, list): _attrs = [] - if isinstance(attrs, six.string_types): + if isinstance(attrs, str): _attrs.append(attrs) else: _attrs = list(attrs) From 513df6baf7e2e07862563fcf188fd73fb53b4247 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Tue, 30 Aug 2022 08:57:51 -0400 Subject: [PATCH 2/3] Add news fragment. --- news/5308.vendor.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/5308.vendor.rst diff --git a/news/5308.vendor.rst b/news/5308.vendor.rst new file mode 100644 index 0000000000..dd75de08a0 --- /dev/null +++ b/news/5308.vendor.rst @@ -0,0 +1 @@ +Vendor in ``requirementslib==2.0.1`` which fixes issue with local install not marked editable, and vendor in ``vistir==0.6.1`` which drops python2 support. From 46f2650680dde71d9934f0b188c4a1b981dc4792 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Tue, 30 Aug 2022 11:58:28 -0400 Subject: [PATCH 3/3] Also remove orderedmultidict --- news/5308.vendor.rst | 1 + pipenv/vendor/orderedmultidict/LICENSE.md | 31 - pipenv/vendor/orderedmultidict/__init__.py | 21 - pipenv/vendor/orderedmultidict/__version__.py | 19 - pipenv/vendor/orderedmultidict/itemlist.py | 158 ---- .../orderedmultidict/orderedmultidict.py | 833 ------------------ pipenv/vendor/vendor.txt | 1 - 7 files changed, 1 insertion(+), 1063 deletions(-) delete mode 100644 pipenv/vendor/orderedmultidict/LICENSE.md delete mode 100755 pipenv/vendor/orderedmultidict/__init__.py delete mode 100755 pipenv/vendor/orderedmultidict/__version__.py delete mode 100755 pipenv/vendor/orderedmultidict/itemlist.py delete mode 100755 pipenv/vendor/orderedmultidict/orderedmultidict.py diff --git a/news/5308.vendor.rst b/news/5308.vendor.rst index dd75de08a0..240c7cdf6d 100644 --- a/news/5308.vendor.rst +++ b/news/5308.vendor.rst @@ -1 +1,2 @@ Vendor in ``requirementslib==2.0.1`` which fixes issue with local install not marked editable, and vendor in ``vistir==0.6.1`` which drops python2 support. +Drops ``orderedmultidict`` from vendoring. diff --git a/pipenv/vendor/orderedmultidict/LICENSE.md b/pipenv/vendor/orderedmultidict/LICENSE.md deleted file mode 100644 index fd832f40a9..0000000000 --- a/pipenv/vendor/orderedmultidict/LICENSE.md +++ /dev/null @@ -1,31 +0,0 @@ -Build Amazing Things. - -*** - -### Unlicense - -This is free and unencumbered software released into the public\ -domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or distribute\ -this software, either in source code form or as a compiled binary, for any\ -purpose, commercial or non-commercial, and by any means. - -In jurisdictions that recognize copyright laws, the author or authors of\ -this software dedicate any and all copyright interest in the software to the\ -public domain. We make this dedication for the benefit of the public at\ -large and to the detriment of our heirs and successors. We intend this\ -dedication to be an overt act of relinquishment in perpetuity of all\ -present and future rights to this software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\ -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\ -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\ -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\ -SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\ -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT\ -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\ -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\ -SOFTWARE. - -For more information, please refer to diff --git a/pipenv/vendor/orderedmultidict/__init__.py b/pipenv/vendor/orderedmultidict/__init__.py deleted file mode 100755 index d122e35cb4..0000000000 --- a/pipenv/vendor/orderedmultidict/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- - -# -# omdict - Ordered Multivalue Dictionary. -# -# Ansgar Grunseid -# grunseid.com -# grunseid@gmail.com -# -# License: Build Amazing Things (Unlicense) -# - -from os.path import dirname, join as pjoin - -from .orderedmultidict import * # noqa - -# Import all variables in __version__.py without explicit imports. -meta = {} -with open(pjoin(dirname(__file__), '__version__.py')) as f: - exec(f.read(), meta) -globals().update(dict((k, v) for k, v in meta.items() if k not in globals())) diff --git a/pipenv/vendor/orderedmultidict/__version__.py b/pipenv/vendor/orderedmultidict/__version__.py deleted file mode 100755 index 29e47e48be..0000000000 --- a/pipenv/vendor/orderedmultidict/__version__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- - -# -# omdict - Ordered Multivalue Dictionary. -# -# Ansgar Grunseid -# grunseid.com -# grunseid@gmail.com -# -# License: Build Amazing Things (Unlicense) -# - -__title__ = 'orderedmultidict' -__version__ = '1.0.1' -__license__ = 'Unlicense' -__author__ = 'Ansgar Grunseid' -__contact__ = 'grunseid@gmail.com' -__description__ = 'Ordered Multivalue Dictionary' -__url__ = 'https://github.com/gruns/orderedmultidict' diff --git a/pipenv/vendor/orderedmultidict/itemlist.py b/pipenv/vendor/orderedmultidict/itemlist.py deleted file mode 100755 index 6d31addce0..0000000000 --- a/pipenv/vendor/orderedmultidict/itemlist.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- - -# -# omdict - Ordered Multivalue Dictionary. -# -# Ansgar Grunseid -# grunseid.com -# grunseid@gmail.com -# -# License: Build Amazing Things (Unlicense) -# - -from __future__ import absolute_import - -from pipenv.vendor.six.moves import zip_longest - -_absent = object() # Marker that means no parameter was provided. - - -class itemnode(object): - - """ - Dictionary key:value items wrapped in a node to be members of itemlist, the - doubly linked list defined below. - """ - - def __init__(self, prev=None, next=None, key=_absent, value=_absent): - self.prev = prev - self.next = next - self.key = key - self.value = value - - -class itemlist(object): - - """ - Doubly linked list of itemnodes. - - This class is used as the key:value item storage of orderedmultidict. - Methods below were only added as needed for use with orderedmultidict, so - some otherwise common list methods may be missing. - """ - - def __init__(self, items=[]): - self.root = itemnode() - self.root.next = self.root.prev = self.root - self.size = 0 - - for key, value in items: - self.append(key, value) - - def append(self, key, value): - tail = self.root.prev if self.root.prev is not self.root else self.root - node = itemnode(tail, self.root, key=key, value=value) - tail.next = node - self.root.prev = node - self.size += 1 - return node - - def removenode(self, node): - node.prev.next = node.next - node.next.prev = node.prev - self.size -= 1 - return self - - def clear(self): - for node, key, value in self: - self.removenode(node) - return self - - def items(self): - return list(self.iteritems()) - - def keys(self): - return list(self.iterkeys()) - - def values(self): - return list(self.itervalues()) - - def iteritems(self): - for node, key, value in self: - yield key, value - - def iterkeys(self): - for node, key, value in self: - yield key - - def itervalues(self): - for node, key, value in self: - yield value - - def reverse(self): - for node, key, value in self: - node.prev, node.next = node.next, node.prev - self.root.prev, self.root.next = self.root.next, self.root.prev - return self - - def __len__(self): - return self.size - - def __iter__(self): - current = self.root.next - while current and current is not self.root: - # Record current.next here in case current.next changes after the - # yield and before we return for the next iteration. For example, - # methods like reverse() will change current.next() before yield - # gets executed again. - nextnode = current.next - yield current, current.key, current.value - current = nextnode - - def __contains__(self, item): - """ - Params: - item: Can either be a (key,value) tuple or an itemnode reference. - """ - node = key = value = _absent - if hasattr(item, '__len__') and callable(item.__len__): - if len(item) == 2: - key, value = item - elif len(item) == 3: - node, key, value = item - else: - node = item - - if node is not _absent or _absent not in [key, value]: - for selfnode, selfkey, selfvalue in self: - if ((node is _absent and key == selfkey and value == selfvalue) - or (node is not _absent and node == selfnode)): - return True - return False - - def __getitem__(self, index): - # Only support direct access to the first or last element, as this is - # all orderedmultidict needs for now. - if index == 0 and self.root.next is not self.root: - return self.root.next - elif index == -1 and self.root.prev is not self.root: - return self.root.prev - raise IndexError(index) - - def __delitem__(self, index): - self.removenode(self[index]) - - def __eq__(self, other): - for (n1, key1, value1), (n2, key2, value2) in zip_longest(self, other): - if key1 != key2 or value1 != value2: - return False - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def __nonzero__(self): - return self.size > 0 - - def __str__(self): - return '[%s]' % self.items() diff --git a/pipenv/vendor/orderedmultidict/orderedmultidict.py b/pipenv/vendor/orderedmultidict/orderedmultidict.py deleted file mode 100755 index fd33f4ad20..0000000000 --- a/pipenv/vendor/orderedmultidict/orderedmultidict.py +++ /dev/null @@ -1,833 +0,0 @@ -# -*- coding: utf-8 -*- - -# -# omdict - Ordered Multivalue Dictionary. -# -# Ansgar Grunseid -# grunseid.com -# grunseid@gmail.com -# -# License: Build Amazing Things (Unlicense) -# - -from __future__ import absolute_import - -import sys -from itertools import chain - -import pipenv.vendor.six as six -from pipenv.vendor.six.moves import map, zip_longest - -from .itemlist import itemlist - -if six.PY2: - from collections import MutableMapping -else: - from collections.abc import MutableMapping -try: - from collections import OrderedDict as odict # Python 2.7 and later. -except ImportError: - from ordereddict import OrderedDict as odict # Python 2.6 and earlier. - - -_absent = object() # Marker that means no parameter was provided. -_items_attr = 'items' if sys.version_info[0] >= 3 else 'iteritems' - - -def callable_attr(obj, attr): - return hasattr(obj, attr) and callable(getattr(obj, attr)) - - -# -# TODO(grun): Create a subclass of list that values(), getlist(), allitems(), -# etc return that the user can manipulate directly to control the omdict() -# object. -# -# For example, users should be able to do things like -# -# omd = omdict([(1,1), (1,11)]) -# omd.values(1).append('sup') -# omd.allitems() == [(1,1), (1,11), (1,'sup')] -# omd.values(1).remove(11) -# omd.allitems() == [(1,1), (1,'sup')] -# omd.values(1).extend(['two', 'more']) -# omd.allitems() == [(1,1), (1,'sup'), (1,'two'), (1,'more')] -# -# or -# -# omd = omdict([(1,1), (1,11)]) -# omd.allitems().extend([(2,2), (2,22)]) -# omd.allitems() == [(1,1), (1,11), (2,2), (2,22)]) -# -# or -# -# omd = omdict() -# omd.values(1) = [1, 11] -# omd.allitems() == [(1,1), (1,11)] -# omd.values(1) = list(map(lambda i: i * -10, omd.values(1))) -# omd.allitems() == [(1,-10), (1,-110)] -# omd.allitems() = filter(lambda (k,v): v > -100, omd.allitems()) -# omd.allitems() == [(1,-10)] -# -# etc. -# -# To accomplish this, subclass list in such a manner that each list element is -# really a two tuple, where the first tuple value is the actual value and the -# second tuple value is a reference to the itemlist node for that value. Users -# only interact with the first tuple values, the actual values, but behind the -# scenes when an element is modified, deleted, inserted, etc, the according -# itemlist nodes are modified, deleted, inserted, etc accordingly. In this -# manner, users can manipulate omdict objects directly through direct list -# manipulation. -# -# Once accomplished, some methods become redundant and should be removed in -# favor of the more intuitive direct value list manipulation. Such redundant -# methods include getlist() (removed in favor of values()?), addlist(), and -# setlist(). -# -# With the removal of many of the 'list' methods, think about renaming all -# remaining 'list' methods to 'values' methods, like poplist() -> popvalues(), -# poplistitem() -> popvaluesitem(), etc. This would be an easy switch for most -# methods, but wouldn't fit others so well. For example, iterlists() would -# become itervalues(), a name extremely similar to iterallvalues() but quite -# different in function. -# - - -class omdict(MutableMapping): - - """ - Ordered Multivalue Dictionary. - - A multivalue dictionary is a dictionary that can store multiple values per - key. An ordered multivalue dictionary is a multivalue dictionary that - retains the order of insertions and deletions. - - Internally, items are stored in a doubly linked list, self._items. A - dictionary, self._map, is also maintained and stores an ordered list of - linked list node references, one for each value associated with that key. - - Standard dict methods interact with the first value associated with a given - key. This means that omdict retains method parity with dict, and a dict - object can be replaced with an omdict object and all interaction will - behave identically. All dict methods that retain parity with omdict are: - - get(), setdefault(), pop(), popitem(), - clear(), copy(), update(), fromkeys(), len() - __getitem__(), __setitem__(), __delitem__(), __contains__(), - items(), keys(), values(), iteritems(), iterkeys(), itervalues(), - - Optional parameters have been added to some dict methods, but because the - added parameters are optional, existing use remains unaffected. An optional - parameter has been added to these methods: - - items(), values(), iteritems(), itervalues() - - New methods have also been added to omdict. Methods with 'list' in their - name interact with lists of values, and methods with 'all' in their name - interact with all items in the dictionary, including multiple items with - the same key. - - The new omdict methods are: - - load(), size(), reverse(), - getlist(), add(), addlist(), set(), setlist(), setdefaultlist(), - poplist(), popvalue(), popvalues(), popitem(), poplistitem(), - allitems(), allkeys(), allvalues(), lists(), listitems(), - iterallitems(), iterallkeys(), iterallvalues(), iterlists(), - iterlistitems() - - Explanations and examples of the new methods above can be found in the - function comments below and online at - - https://github.com/gruns/orderedmultidict - - Additional omdict information and documentation can also be found at the - above url. - """ - - def __init__(self, *args, **kwargs): - # Doubly linked list of itemnodes. Each itemnode stores a key:value - # item. - self._items = itemlist() - - # Ordered dictionary of keys and itemnode references. Each itemnode - # reference points to one of that keys values. - self._map = odict() - - self.load(*args, **kwargs) - - def load(self, *args, **kwargs): - """ - Clear all existing key:value items and import all key:value items from - . If multiple values exist for the same key in , they - are all be imported. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.load([(4,4), (4,44), (5,5)]) - omd.allitems() == [(4,4), (4,44), (5,5)] - - Returns: . - """ - self.clear() - self.updateall(*args, **kwargs) - return self - - def copy(self): - return self.__class__(self.allitems()) - - def clear(self): - self._map.clear() - self._items.clear() - - def size(self): - """ - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.size() == 5 - - Returns: Total number of items, including multiple items with the same - key. - """ - return len(self._items) - - @classmethod - def fromkeys(cls, iterable, value=None): - return cls([(key, value) for key in iterable]) - - def has_key(self, key): - return key in self - - def update(self, *args, **kwargs): - self._update_updateall(True, *args, **kwargs) - - def updateall(self, *args, **kwargs): - """ - Update this dictionary with the items from , replacing - existing key:value items with shared keys before adding new key:value - items. - - Example: - omd = omdict([(1,1), (2,2)]) - omd.updateall([(2,'two'), (1,'one'), (2,222), (1,111)]) - omd.allitems() == [(1, 'one'), (2, 'two'), (2, 222), (1, 111)] - - Returns: . - """ - self._update_updateall(False, *args, **kwargs) - return self - - def _update_updateall(self, replace_at_most_one, *args, **kwargs): - # Bin the items in and into or - # . Items in are new values to replace old - # values for a given key, and items in are new items to be - # added. - replacements, leftovers = dict(), [] - for mapping in chain(args, [kwargs]): - self._bin_update_items( - self._items_iterator(mapping), replace_at_most_one, - replacements, leftovers) - - # First, replace existing values for each key. - for key, values in six.iteritems(replacements): - self.setlist(key, values) - # Then, add the leftover items to the end of the list of all items. - for key, value in leftovers: - self.add(key, value) - - def _bin_update_items(self, items, replace_at_most_one, - replacements, leftovers): - """ - are modified directly, ala pass by - reference. - """ - for key, value in items: - # If there are existing items with key that have yet to be - # marked for replacement, mark that item's value to be replaced by - # by appending it to . - if key in self and key not in replacements: - replacements[key] = [value] - elif (key in self and not replace_at_most_one and - len(replacements[key]) < len(self.values(key))): - replacements[key].append(value) - else: - if replace_at_most_one: - replacements[key] = [value] - else: - leftovers.append((key, value)) - - def _items_iterator(self, container): - cont = container - iterator = iter(cont) - if callable_attr(cont, 'iterallitems'): - iterator = cont.iterallitems() - elif callable_attr(cont, 'allitems'): - iterator = iter(cont.allitems()) - elif callable_attr(cont, 'iteritems'): - iterator = cont.iteritems() - elif callable_attr(cont, 'items'): - iterator = iter(cont.items()) - return iterator - - def get(self, key, default=None): - if key in self: - return self._map[key][0].value - return default - - def getlist(self, key, default=[]): - """ - Returns: The list of values for if is in the dictionary, - else . If is not provided, an empty list is - returned. - """ - if key in self: - return [node.value for node in self._map[key]] - return default - - def setdefault(self, key, default=None): - if key in self: - return self[key] - self.add(key, default) - return default - - def setdefaultlist(self, key, defaultlist=[None]): - """ - Similar to setdefault() except is a list of values to set - for . If already exists, its existing list of values is - returned. - - If isn't a key and is an empty list, [], no values - are added for and will not be added as a key. - - Returns: List of 's values if exists in the dictionary, - otherwise . - """ - if key in self: - return self.getlist(key) - self.addlist(key, defaultlist) - return defaultlist - - def add(self, key, value=None): - """ - Add to the list of values for . If is not in the - dictionary, then is added as the sole value for . - - Example: - omd = omdict() - omd.add(1, 1) # omd.allitems() == [(1,1)] - omd.add(1, 11) # omd.allitems() == [(1,1), (1,11)] - omd.add(2, 2) # omd.allitems() == [(1,1), (1,11), (2,2)] - - Returns: . - """ - self._map.setdefault(key, []) - node = self._items.append(key, value) - self._map[key].append(node) - return self - - def addlist(self, key, valuelist=[]): - """ - Add the values in to the list of values for . If - is not in the dictionary, the values in become the values - for . - - Example: - omd = omdict([(1,1)]) - omd.addlist(1, [11, 111]) - omd.allitems() == [(1, 1), (1, 11), (1, 111)] - omd.addlist(2, [2]) - omd.allitems() == [(1, 1), (1, 11), (1, 111), (2, 2)] - - Returns: . - """ - for value in valuelist: - self.add(key, value) - return self - - def set(self, key, value=None): - """ - Sets 's value to . Identical in function to __setitem__(). - - Returns: . - """ - self[key] = value - return self - - def setlist(self, key, values): - """ - Sets 's list of values to . Existing items with key - are first replaced with new values from . Any remaining old - items that haven't been replaced with new values are deleted, and any - new values from that don't have corresponding items with - to replace are appended to the end of the list of all items. - - If values is an empty list, [], is deleted, equivalent in action - to del self[]. - - Example: - omd = omdict([(1,1), (2,2)]) - omd.setlist(1, [11, 111]) - omd.allitems() == [(1,11), (2,2), (1,111)] - - omd = omdict([(1,1), (1,11), (2,2), (1,111)]) - omd.setlist(1, [None]) - omd.allitems() == [(1,None), (2,2)] - - omd = omdict([(1,1), (1,11), (2,2), (1,111)]) - omd.setlist(1, []) - omd.allitems() == [(2,2)] - - Returns: . - """ - if not values and key in self: - self.pop(key) - else: - it = zip_longest( - list(self._map.get(key, [])), values, fillvalue=_absent) - for node, value in it: - if node is not _absent and value is not _absent: - node.value = value - elif node is _absent: - self.add(key, value) - elif value is _absent: - self._map[key].remove(node) - self._items.removenode(node) - return self - - def removevalues(self, key, values): - """ - Removes all from the values of . If has no - remaining values after removevalues(), the key is popped. - - Example: - omd = omdict([(1, 1), (1, 11), (1, 1), (1, 111)]) - omd.removevalues(1, [1, 111]) - omd.allitems() == [(1, 11)] - - Returns: . - """ - self.setlist(key, [v for v in self.getlist(key) if v not in values]) - return self - - def pop(self, key, default=_absent): - if key in self: - return self.poplist(key)[0] - elif key not in self._map and default is not _absent: - return default - raise KeyError(key) - - def poplist(self, key, default=_absent): - """ - If is in the dictionary, pop it and return its list of values. If - is not in the dictionary, return . KeyError is raised if - is not provided and is not in the dictionary. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.poplist(1) == [1, 11, 111] - omd.allitems() == [(2,2), (3,3)] - omd.poplist(2) == [2] - omd.allitems() == [(3,3)] - - Raises: KeyError if isn't in the dictionary and isn't - provided. - Returns: List of 's values. - """ - if key in self: - values = self.getlist(key) - del self._map[key] - for node, nodekey, nodevalue in self._items: - if nodekey == key: - self._items.removenode(node) - return values - elif key not in self._map and default is not _absent: - return default - raise KeyError(key) - - def popvalue(self, key, value=_absent, default=_absent, last=True): - """ - If is provided, pops the first or last (key,value) item in the - dictionary if is in the dictionary. - - If is not provided, pops the first or last value for if - is in the dictionary. - - If no longer has any values after a popvalue() call, is - removed from the dictionary. If isn't in the dictionary and - was provided, return default. KeyError is raised if - is not provided and is not in the dictionary. ValueError is - raised if is provided but isn't a value for . - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3), (2,22)]) - omd.popvalue(1) == 111 - omd.allitems() == [(1,11), (1,111), (2,2), (3,3), (2,22)] - omd.popvalue(1, last=False) == 1 - omd.allitems() == [(1,11), (2,2), (3,3), (2,22)] - omd.popvalue(2, 2) == 2 - omd.allitems() == [(1,11), (3,3), (2,22)] - omd.popvalue(1, 11) == 11 - omd.allitems() == [(3,3), (2,22)] - omd.popvalue('not a key', default='sup') == 'sup' - - Params: - last: Boolean whether to return 's first value ( is False) - or last value ( is True). - Raises: - KeyError if isn't in the dictionary and isn't - provided. - ValueError if isn't a value for . - Returns: The first or last of 's values. - """ - def pop_node_with_index(key, index): - node = self._map[key].pop(index) - if not self._map[key]: - del self._map[key] - self._items.removenode(node) - return node - - if key in self: - if value is not _absent: - if last: - pos = self.values(key)[::-1].index(value) - else: - pos = self.values(key).index(value) - if pos == -1: - raise ValueError(value) - else: - index = (len(self.values(key)) - 1 - pos) if last else pos - return pop_node_with_index(key, index).value - else: - return pop_node_with_index(key, -1 if last else 0).value - elif key not in self._map and default is not _absent: - return default - raise KeyError(key) - - def popitem(self, fromall=False, last=True): - """ - Pop and return a key:value item. - - If is False, items()[0] is popped if is False or - items()[-1] is popped if is True. All remaining items with the - same key are removed. - - If is True, allitems()[0] is popped if is False or - allitems()[-1] is popped if is True. Any remaining items with - the same key remain. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.popitem() == (3,3) - omd.popitem(fromall=False, last=False) == (1,1) - omd.popitem(fromall=False, last=False) == (2,2) - - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.popitem(fromall=True, last=False) == (1,1) - omd.popitem(fromall=True, last=False) == (1,11) - omd.popitem(fromall=True, last=True) == (3,3) - omd.popitem(fromall=True, last=False) == (1,111) - - Params: - fromall: Whether to pop an item from items() ( is True) or - allitems() ( is False). - last: Boolean whether to pop the first item or last item of items() - or allitems(). - Raises: KeyError if the dictionary is empty. - Returns: The first or last item from item() or allitem(). - """ - if not self._items: - raise KeyError('popitem(): %s is empty' % self.__class__.__name__) - - if fromall: - node = self._items[-1 if last else 0] - key = node.key - return key, self.popvalue(key, last=last) - else: - key = list(self._map.keys())[-1 if last else 0] - return key, self.pop(key) - - def poplistitem(self, last=True): - """ - Pop and return a key:valuelist item comprised of a key and that key's - list of values. If is False, a key:valuelist item comprised of - keys()[0] and its list of values is popped and returned. If is - True, a key:valuelist item comprised of keys()[-1] and its list of - values is popped and returned. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.poplistitem(last=True) == (3,[3]) - omd.poplistitem(last=False) == (1,[1,11,111]) - - Params: - last: Boolean whether to pop the first or last key and its associated - list of values. - Raises: KeyError if the dictionary is empty. - Returns: A two-tuple comprised of the first or last key and its - associated list of values. - """ - if not self._items: - s = 'poplistitem(): %s is empty' % self.__class__.__name__ - raise KeyError(s) - - key = self.keys()[-1 if last else 0] - return key, self.poplist(key) - - def items(self, key=_absent): - """ - Raises: KeyError if is provided and not in the dictionary. - Returns: List created from iteritems(). Only items with key - are returned if is provided and is a dictionary key. - """ - return list(self.iteritems(key)) - - def keys(self): - return list(self.iterkeys()) - - def values(self, key=_absent): - """ - Raises: KeyError if is provided and not in the dictionary. - Returns: List created from itervalues().If is provided and - is a dictionary key, only values of items with key are - returned. - """ - if key is not _absent and key in self._map: - return self.getlist(key) - return list(self.itervalues()) - - def lists(self): - """ - Returns: List created from iterlists(). - """ - return list(self.iterlists()) - - def listitems(self): - """ - Returns: List created from iterlistitems(). - """ - return list(self.iterlistitems()) - - def iteritems(self, key=_absent): - """ - Parity with dict.iteritems() except the optional parameter has - been added. If is provided, only items with the provided key are - iterated over. KeyError is raised if is provided and not in the - dictionary. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iteritems(1) -> (1,1) -> (1,11) -> (1,111) - omd.iteritems() -> (1,1) -> (2,2) -> (3,3) - - Raises: KeyError if is provided and not in the dictionary. - Returns: An iterator over the items() of the dictionary, or only items - with the key if is provided. - """ - if key is not _absent: - if key in self: - items = [(node.key, node.value) for node in self._map[key]] - return iter(items) - raise KeyError(key) - items = six.iteritems(self._map) - return iter((key, nodes[0].value) for (key, nodes) in items) - - def iterkeys(self): - return six.iterkeys(self._map) - - def itervalues(self, key=_absent): - """ - Parity with dict.itervalues() except the optional parameter has - been added. If is provided, only values from items with the - provided key are iterated over. KeyError is raised if is provided - and not in the dictionary. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.itervalues(1) -> 1 -> 11 -> 111 - omd.itervalues() -> 1 -> 11 -> 111 -> 2 -> 3 - - Raises: KeyError if is provided and isn't in the dictionary. - Returns: An iterator over the values() of the dictionary, or only the - values of key if is provided. - """ - if key is not _absent: - if key in self: - return iter([node.value for node in self._map[key]]) - raise KeyError(key) - return iter([nodes[0].value for nodes in six.itervalues(self._map)]) - - def allitems(self, key=_absent): - ''' - Raises: KeyError if is provided and not in the dictionary. - Returns: List created from iterallitems(). - ''' - return list(self.iterallitems(key)) - - def allkeys(self): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.allkeys() == [1,1,1,2,3] - - Returns: List created from iterallkeys(). - ''' - return list(self.iterallkeys()) - - def allvalues(self, key=_absent): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.allvalues() == [1,11,111,2,3] - omd.allvalues(1) == [1,11,111] - - Raises: KeyError if is provided and not in the dictionary. - Returns: List created from iterallvalues(). - ''' - return list(self.iterallvalues(key)) - - def iterallitems(self, key=_absent): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iterallitems() == (1,1) -> (1,11) -> (1,111) -> (2,2) -> (3,3) - omd.iterallitems(1) == (1,1) -> (1,11) -> (1,111) - - Raises: KeyError if is provided and not in the dictionary. - Returns: An iterator over every item in the diciontary. If is - provided, only items with the key are iterated over. - ''' - if key is not _absent: - # Raises KeyError if is not in self._map. - return self.iteritems(key) - return self._items.iteritems() - - def iterallkeys(self): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iterallkeys() == 1 -> 1 -> 1 -> 2 -> 3 - - Returns: An iterator over the keys of every item in the dictionary. - ''' - return self._items.iterkeys() - - def iterallvalues(self, key=_absent): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iterallvalues() == 1 -> 11 -> 111 -> 2 -> 3 - - Returns: An iterator over the values of every item in the dictionary. - ''' - if key is not _absent: - if key in self: - return iter(self.getlist(key)) - raise KeyError(key) - return self._items.itervalues() - - def iterlists(self): - ''' - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iterlists() -> [1,11,111] -> [2] -> [3] - - Returns: An iterator over the list comprised of the lists of values for - each key. - ''' - return map(lambda key: self.getlist(key), self) - - def iterlistitems(self): - """ - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.iterlistitems() -> (1,[1,11,111]) -> (2,[2]) -> (3,[3]) - - Returns: An iterator over the list of key:valuelist items. - """ - return map(lambda key: (key, self.getlist(key)), self) - - def reverse(self): - """ - Reverse the order of all items in the dictionary. - - Example: - omd = omdict([(1,1), (1,11), (1,111), (2,2), (3,3)]) - omd.reverse() - omd.allitems() == [(3,3), (2,2), (1,111), (1,11), (1,1)] - - Returns: . - """ - for key in six.iterkeys(self._map): - self._map[key].reverse() - self._items.reverse() - return self - - def __eq__(self, other): - if callable_attr(other, 'iterallitems'): - myiter, otheriter = self.iterallitems(), other.iterallitems() - for i1, i2 in zip_longest(myiter, otheriter, fillvalue=_absent): - if i1 != i2 or i1 is _absent or i2 is _absent: - return False - elif not hasattr(other, '__len__') or not hasattr(other, _items_attr): - return False - # Ignore order so we can compare ordered omdicts with unordered dicts. - else: - if len(self) != len(other): - return False - for key, value in six.iteritems(other): - if self.get(key, _absent) != value: - return False - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def __len__(self): - return len(self._map) - - def __iter__(self): - for key in self.iterkeys(): - yield key - - def __contains__(self, key): - return key in self._map - - def __getitem__(self, key): - if key in self: - return self.get(key) - raise KeyError(key) - - def __setitem__(self, key, value): - self.setlist(key, [value]) - - def __delitem__(self, key): - return self.pop(key) - - def __nonzero__(self): - return bool(self._map) - - def __str__(self): - return '{%s}' % ', '.join( - map(lambda p: '%r: %r' % (p[0], p[1]), self.iterallitems())) - - def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, self.allitems()) - - def __or__(self, other): - return self.__class__(chain(_get_items(self), _get_items(other))) - - def __ior__(self, other): - for k, v in _get_items(other): - self.add(k, value=v) - return self - - -def _get_items(mapping): - """Find item iterator for an object.""" - names = ('iterallitems', 'allitems', 'iteritems', 'items') - exist = (n for n in names if callable_attr(mapping, n)) - for a in exist: - return getattr(mapping, a)() - raise TypeError( - "Object {} has no compatible items interface.".format(mapping)) diff --git a/pipenv/vendor/vendor.txt b/pipenv/vendor/vendor.txt index 1ee6ade784..db39b82921 100644 --- a/pipenv/vendor/vendor.txt +++ b/pipenv/vendor/vendor.txt @@ -9,7 +9,6 @@ dparse==0.5.1 idna==3.2 iso8601==0.1.16 markupsafe==2.0.1 -orderedmultidict==1.0.1 parse==1.19.0 pexpect==4.8.0 pipdeptree==2.2.1