Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix direct dependency URL parsing #4255

Merged
merged 18 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/3976.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a bug which prevented resolution of direct URL dependencies which have PEP508 style direct url VCS sub-dependencies with subdirectories.
1 change: 1 addition & 0 deletions news/4226.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``Requires-Python`` values specifying constraint versions of python starting from ``1.x`` will now be parsed successfully.
11 changes: 11 additions & 0 deletions news/4226.vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Updated vendored dependencies to latest versions for security and bug fixes:

- **requirementslib** ``1.5.8`` => ``1.5.9``
- **vistir** ``0.5.0`` => ``0.5.1``
- **jinja2** ``2.11.1`` => ``2.11.2``
- **click** ``7.1.1`` => ``7.1.2``
- **dateutil** ``(none)`` => ``2.8.1``
- **backports.functools_lru_cache** ``1.5.0`` => ``1.6.1``
- **enum34** ``1.1.6`` => ``1.1.10``
- **toml** ``0.10.0`` => ``0.10.1``
- **importlib_resources** ``1.4.0`` => ``1.5.0``
15 changes: 6 additions & 9 deletions pipenv/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ def get_deps_from_req(cls, req, resolver=None):
constraints.add(line)
# ensure the top level entry remains as provided
# note that we shouldn't pin versions for editable vcs deps
if (not req.is_vcs or (req.is_vcs and not req.editable)):
if not req.is_vcs:
if req.specifiers:
locked_deps[name]["version"] = req.specifiers
elif parsed_line.setup_info and parsed_line.setup_info.version:
Expand Down Expand Up @@ -997,6 +997,8 @@ def clean_results(self):
for req, ireq in reqs:
if (req.vcs and req.editable and not req.is_direct_url):
continue
elif req.normalized_name in self.skipped.keys():
continue
collected_hashes = self.collect_hashes(ireq)
req = req.add_hashes(collected_hashes)
if not collected_hashes and self._should_include_hash(ireq):
Expand Down Expand Up @@ -1041,9 +1043,9 @@ def format_requirement_for_lockfile(req, markers_lookup, index_lookup, hashes=No
entry["version"] = pf_entry.lstrip("=")
else:
entry.update(pf_entry)
if version is not None:
if version is not None and not req.is_vcs:
entry["version"] = version
if req.line_instance.is_direct_url:
if req.line_instance.is_direct_url and not req.is_vcs:
entry["file"] = req.req.uri
if hashes:
entry["hashes"] = sorted(set(hashes))
Expand All @@ -1054,7 +1056,7 @@ def format_requirement_for_lockfile(req, markers_lookup, index_lookup, hashes=No
entry.update({"markers": markers})
entry = translate_markers(entry)
if req.vcs or req.editable:
for key in ("index", "version"):
for key in ("index", "version", "file"):
try:
del entry[key]
except KeyError:
Expand Down Expand Up @@ -1879,11 +1881,6 @@ def get_vcs_deps(
lockfile[name] = requirement.pipfile_entry[1]
lockfile[name]['ref'] = commit_hash
result.append(requirement)
version = requirement.specifiers
if not version and requirement.specifiers:
version = requirement.specifiers
if version:
lockfile[name]['version'] = version
except OSError:
continue
return result, lockfile
Expand Down
4 changes: 2 additions & 2 deletions pipenv/vendor/appdirs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

__version_info__ = (1, 4, 3)
__version__ = '.'.join(map(str, __version_info__))
__version__ = "1.4.4"
__version_info__ = tuple(int(segment) for segment in __version__.split("."))


import sys
Expand Down
7 changes: 4 additions & 3 deletions pipenv/vendor/backports/enum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

__all__ = ['Enum', 'IntEnum', 'unique']

version = 1, 1, 6
version = 1, 1, 10

pyver = float('%s.%s' % _sys.version_info[:2])

Expand Down Expand Up @@ -183,7 +183,8 @@ def __new__(metacls, cls, bases, classdict):
else:
del classdict['_order_']
if pyver < 3.0:
_order_ = _order_.replace(',', ' ').split()
if isinstance(_order_, basestring):
_order_ = _order_.replace(',', ' ').split()
aliases = [name for name in members if name not in _order_]
_order_ += aliases

Expand Down Expand Up @@ -463,7 +464,7 @@ def _create_(cls, class_name, names=None, module=None, type=None, start=1):
_order_.append(member_name)
# only set _order_ in classdict if name/value was not from a mapping
if not isinstance(item, basestring):
classdict['_order_'] = ' '.join(_order_)
classdict['_order_'] = _order_
enum_class = metacls.__new__(metacls, class_name, bases, classdict)

# TODO: replace the frame hack if a blessed way to know the calling
Expand Down
50 changes: 31 additions & 19 deletions pipenv/vendor/backports/functools_lru_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@


@functools.wraps(functools.update_wrapper)
def update_wrapper(wrapper,
wrapped,
assigned = functools.WRAPPER_ASSIGNMENTS,
updated = functools.WRAPPER_UPDATES):
def update_wrapper(
wrapper,
wrapped,
assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES,
):
"""
Patch two bugs in functools.update_wrapper.
"""
Expand All @@ -34,10 +36,17 @@ def __hash__(self):
return self.hashvalue


def _make_key(args, kwds, typed,
kwd_mark=(object(),),
fasttypes=set([int, str, frozenset, type(None)]),
sorted=sorted, tuple=tuple, type=type, len=len):
def _make_key(
args,
kwds,
typed,
kwd_mark=(object(),),
fasttypes=set([int, str, frozenset, type(None)]),
sorted=sorted,
tuple=tuple,
type=type,
len=len,
):
'Make a cache key from optionally typed positional and keyword arguments'
key = args
if kwds:
Expand Down Expand Up @@ -82,16 +91,16 @@ def lru_cache(maxsize=100, typed=False):
def decorating_function(user_function):

cache = dict()
stats = [0, 0] # make statistics updateable non-locally
HITS, MISSES = 0, 1 # names for the stats fields
stats = [0, 0] # make statistics updateable non-locally
HITS, MISSES = 0, 1 # names for the stats fields
make_key = _make_key
cache_get = cache.get # bound method to lookup key or return None
_len = len # localize the global len() function
lock = RLock() # because linkedlist updates aren't threadsafe
root = [] # root of the circular doubly linked list
root[:] = [root, root, None, None] # initialize by pointing to self
nonlocal_root = [root] # make updateable non-locally
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields
cache_get = cache.get # bound method to lookup key or return None
_len = len # localize the global len() function
lock = RLock() # because linkedlist updates aren't threadsafe
root = [] # root of the circular doubly linked list
root[:] = [root, root, None, None] # initialize by pointing to self
nonlocal_root = [root] # make updateable non-locally
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields

if maxsize == 0:

Expand All @@ -106,7 +115,9 @@ def wrapper(*args, **kwds):
def wrapper(*args, **kwds):
# simple caching without ordering or size limit
key = make_key(args, kwds, typed)
result = cache_get(key, root) # root used here as a unique not-found sentinel
result = cache_get(
key, root
) # root used here as a unique not-found sentinel
if result is not root:
stats[HITS] += 1
return result
Expand All @@ -123,7 +134,8 @@ def wrapper(*args, **kwds):
with lock:
link = cache_get(key)
if link is not None:
# record recent use of the key by moving it to the front of the list
# record recent use of the key by moving it
# to the front of the list
root, = nonlocal_root
link_prev, link_next, key, result = link
link_prev[NEXT] = link_next
Expand Down
2 changes: 1 addition & 1 deletion pipenv/vendor/click/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@
# literals.
disable_unicode_literals_warning = False

__version__ = "7.1.1"
__version__ = "7.1.2"
4 changes: 0 additions & 4 deletions pipenv/vendor/click/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,6 @@ def seekable(self):
iteritems = lambda x: x.iteritems()
range_type = xrange

from pipes import quote as shlex_quote

def is_bytes(x):
return isinstance(x, (buffer, bytearray))

Expand Down Expand Up @@ -284,8 +282,6 @@ def filename_to_ui(value):
isidentifier = lambda x: x.isidentifier()
iteritems = lambda x: iter(x.items())

from shlex import quote as shlex_quote

def is_bytes(x):
return isinstance(x, (bytes, memoryview, bytearray))

Expand Down
22 changes: 9 additions & 13 deletions pipenv/vendor/click/_termui_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from ._compat import isatty
from ._compat import open_stream
from ._compat import range_type
from ._compat import shlex_quote
from ._compat import strip_ansi
from ._compat import term_len
from ._compat import WIN
Expand Down Expand Up @@ -346,10 +345,7 @@ def pager(generator, color=None):
fd, filename = tempfile.mkstemp()
os.close(fd)
try:
if (
hasattr(os, "system")
and os.system("more {}".format(shlex_quote(filename))) == 0
):
if hasattr(os, "system") and os.system('more "{}"'.format(filename)) == 0:
return _pipepager(generator, "more", color)
return _nullpager(stdout, generator, color)
finally:
Expand Down Expand Up @@ -418,7 +414,7 @@ def _tempfilepager(generator, cmd, color):
with open_stream(filename, "wb")[0] as f:
f.write(text.encode(encoding))
try:
os.system("{} {}".format(shlex_quote(cmd), shlex_quote(filename)))
os.system('{} "{}"'.format(cmd, filename))
finally:
os.unlink(filename)

Expand Down Expand Up @@ -463,9 +459,7 @@ def edit_file(self, filename):
environ = None
try:
c = subprocess.Popen(
"{} {}".format(shlex_quote(editor), shlex_quote(filename)),
env=environ,
shell=True,
'{} "{}"'.format(editor, filename), env=environ, shell=True,
)
exit_code = c.wait()
if exit_code != 0:
Expand Down Expand Up @@ -536,16 +530,18 @@ def _unquote_file(url):
elif WIN:
if locate:
url = _unquote_file(url)
args = "explorer /select,{}".format(shlex_quote(url))
args = 'explorer /select,"{}"'.format(_unquote_file(url.replace('"', "")))
else:
args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex_quote(url))
args = 'start {} "" "{}"'.format(
"/WAIT" if wait else "", url.replace('"', "")
)
return os.system(args)
elif CYGWIN:
if locate:
url = _unquote_file(url)
args = "cygstart {}".format(shlex_quote(os.path.dirname(url)))
args = 'cygstart "{}"'.format(os.path.dirname(url).replace('"', ""))
else:
args = "cygstart {} {}".format("-w" if wait else "", shlex_quote(url))
args = 'cygstart {} "{}"'.format("-w" if wait else "", url.replace('"', ""))
return os.system(args)

try:
Expand Down
54 changes: 54 additions & 0 deletions pipenv/vendor/dateutil/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Copyright 2017- Paul Ganssle <paul@ganssle.io>
Copyright 2017- dateutil contributors (see AUTHORS file)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

The above license applies to all contributions after 2017-12-01, as well as
all contributions that have been re-licensed (see AUTHORS file for the list of
contributors who have re-licensed their code).
--------------------------------------------------------------------------------
dateutil - Extensions to the standard Python datetime module.

Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
Copyright (c) 2012-2014 - Tomi Pieviläinen <tomi.pievilainen@iki.fi>
Copyright (c) 2014-2016 - Yaron de Leeuw <me@jarondl.net>
Copyright (c) 2015- - Paul Ganssle <paul@ganssle.io>
Copyright (c) 2015- - dateutil contributors (see AUTHORS file)

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The above BSD License Applies to all code, even that also covered by Apache 2.0.
8 changes: 8 additions & 0 deletions pipenv/vendor/dateutil/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
try:
from ._version import version as __version__
except ImportError:
__version__ = 'unknown'

__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz',
'utils', 'zoneinfo']
43 changes: 43 additions & 0 deletions pipenv/vendor/dateutil/_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Common code used in multiple modules.
"""


class weekday(object):
__slots__ = ["weekday", "n"]

def __init__(self, weekday, n=None):
self.weekday = weekday
self.n = n

def __call__(self, n):
if n == self.n:
return self
else:
return self.__class__(self.weekday, n)

def __eq__(self, other):
try:
if self.weekday != other.weekday or self.n != other.n:
return False
except AttributeError:
return False
return True

def __hash__(self):
return hash((
self.weekday,
self.n,
))

def __ne__(self, other):
return not (self == other)

def __repr__(self):
s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday]
if not self.n:
return s
else:
return "%s(%+d)" % (s, self.n)

# vim:ts=4:sw=4:et
4 changes: 4 additions & 0 deletions pipenv/vendor/dateutil/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
version = '2.8.1'
Loading