diff --git a/HISTORY.txt b/HISTORY.txt index 9a9967e7..7382a8e4 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -1,3 +1,24 @@ +11.10.4: + - Bugfix release (_mkstmp_inner backport breaks python3.4/3.5 compat) +11.10.3: + - Bugfix release (break dependency on pathlib2). +11.10.2: + - Backport NamedTemporaryFile for python 2. + - Implement atomic lockfile writing / rewriting. + - Allow non-interactive pyenv installations for CI. + - Bugfix regression which restricted pipfiles to two sources. + - Update default python 2.7 version to 2.7.15. + - Fix bug preventing usage within premade virtualenvs. + - Add PIPENV_MAX_RETRIES environment variable to allow retrying installs. + - Fix regression with `pipenv sync` which caused it to lock if out of sync. + - Update colorblind mode to respect progress bars. + - Use `\n` to generate new lockfiles and pipfiles, default to current newlines. + - Fix bug with environment variable expansion writing back to Pipfiles when + running `pipenv install ` + - Accurately parse extras from egg fragments. + - Allow `editable=False` in pipfile. + - Fix `keep-outdated` argument for installation (previously unenforced). + - Update vendoring scripts to include licenses for vendored pip. 11.10.1: - Fix broken resolution when using multiple sources in pipfiles and passing `--skip-lock`. diff --git a/pipenv/__version__.py b/pipenv/__version__.py index 9714b0cd..ca48c4bd 100644 --- a/pipenv/__version__.py +++ b/pipenv/__version__.py @@ -2,4 +2,4 @@ # // ) ) / / // ) ) //___) ) // ) ) || / / # //___/ / / / //___/ / // // / / || / / # // / / // ((____ // / / ||/ / -__version__ = '11.10.2.dev1' +__version__ = '11.10.4' diff --git a/pipenv/_compat.py b/pipenv/_compat.py index 6769d8d4..14326813 100644 --- a/pipenv/_compat.py +++ b/pipenv/_compat.py @@ -8,6 +8,7 @@ import functools import io import os import six +import sys import warnings from tempfile import _bin_openflags, gettempdir, _mkstemp_inner, mkdtemp from .utils import (logging, rmtree) @@ -257,7 +258,7 @@ def NamedTemporaryFile( # the file when it is closed. This is only supported by Windows. if os.name == "nt" and delete: flags |= os.O_TEMPORARY - if six.PY2: + 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) diff --git a/pipenv/core.py b/pipenv/core.py index 79357ce5..4d1b559d 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -2012,6 +2012,14 @@ def do_install( err=True, ) click.echo(crayons.blue(format_pip_error(c.err)), err=True) + if 'setup.py egg_info' in c.err: + click.echo( + "This is likely caused by a bug in {0}. " + "Report this to its maintainers.".format( + crayons.green(package_name), + ), + err=True, + ) requirements_directory.cleanup() sys.exit(1) click.echo( diff --git a/pipenv/environments.py b/pipenv/environments.py index f5d53a1a..3837363d 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -23,6 +23,9 @@ PIPENV_COLORBLIND = bool(os.environ.get('PIPENV_COLORBLIND')) PIPENV_NOSPIN = bool(os.environ.get('PIPENV_NOSPIN')) # Tells Pipenv how many rounds of resolving to do for Pip-Tools. PIPENV_MAX_ROUNDS = int(os.environ.get('PIPENV_MAX_ROUNDS', '16')) +# Specify how many retries Pipenv should attempt for network requests. +default_retries = '1' if 'CI' in os.environ else '0' +PIPENV_MAX_RETRIES = int(os.environ.get('PIPENV_MAX_RETRIES', default_retries)) # Specify a custom Pipfile location. PIPENV_PIPFILE = os.environ.get('PIPENV_PIPFILE') # Tells Pipenv which Python to default to, when none is provided. diff --git a/pipenv/patched/pew/_utils.py b/pipenv/patched/pew/_utils.py index c45c37e0..a45c227f 100644 --- a/pipenv/patched/pew/_utils.py +++ b/pipenv/patched/pew/_utils.py @@ -9,7 +9,7 @@ from functools import partial, wraps try: from pathlib import Path except ImportError: - from pathlib2 import Path + from pipenv.vendor.pathlib2 import Path from tempfile import NamedTemporaryFile as _ntf try: from shutil import which diff --git a/pipenv/patched/pew/pew.py b/pipenv/patched/pew/pew.py index 960a1263..2d3889a0 100644 --- a/pipenv/patched/pew/pew.py +++ b/pipenv/patched/pew/pew.py @@ -11,7 +11,7 @@ from subprocess import CalledProcessError try: from pathlib import Path except ImportError: - from pathlib2 import Path + from pipenv.vendor.pathlib2 import Path try: from shutil import get_terminal_size diff --git a/pipenv/utils.py b/pipenv/utils.py index bc1d54d0..973b1c83 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -45,7 +45,11 @@ except ImportError: from distutils.spawn import find_executable from contextlib import contextmanager from .pep508checker import lookup -from .environments import PIPENV_MAX_ROUNDS, PIPENV_CACHE_DIR +from .environments import ( + PIPENV_MAX_ROUNDS, + PIPENV_CACHE_DIR, + PIPENV_MAX_RETRIES +) try: from collections.abc import Mapping @@ -72,6 +76,8 @@ def _get_requests_session(): return requests_session import requests requests_session = requests.Session() + adapter = requests.adapters.HTTPAdapter(max_retries=PIPENV_MAX_RETRIES) + requests_session.mount('https://pypi.org/pypi', adapter) return requests_session diff --git a/pipenv/vendor/pip9/__main__.py b/pipenv/vendor/pip9/__main__.py index da041f92..9849a65c 100644 --- a/pipenv/vendor/pip9/__main__.py +++ b/pipenv/vendor/pip9/__main__.py @@ -16,4 +16,4 @@ if __package__ == '': import pip9 # noqa if __name__ == '__main__': - sys.exit(pip.main()) + sys.exit(pip9.main()) diff --git a/setup.py b/setup.py index 5954684e..8dc09a32 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,6 @@ required = [ 'setuptools>=36.2.1', 'virtualenv-clone>=0.2.5', 'virtualenv', - 'pathlib2==2.1.0;python_version<"3.4"', 'requests[security];python_version<"2.7"', 'ordereddict;python_version<"2.7"', ] @@ -88,7 +87,7 @@ class UploadCommand(Command): except FileNotFoundError: pass self.status('Building Source distribution…') - os.system('{0} setup.py sdist'.format(sys.executable)) + os.system('{0} setup.py sdist bdist_wheel'.format(sys.executable)) self.status('Uploading the package to PyPi via Twine…') os.system('twine upload dist/*') self.status('Pushing git tags…') @@ -114,6 +113,7 @@ setup( ] }, package_data={ + '': ['LICENSE', 'NOTICES'], "pipenv.vendor.requests": ["*.pem"], "pipenv.vendor.certifi": ["*.pem"], "pipenv.patched.notpip._vendor.certifi": ["*.pem"], diff --git a/tasks/vendoring/patches/patched/pew.patch b/tasks/vendoring/patches/patched/pew.patch index 27513fe3..e6e5f737 100644 --- a/tasks/vendoring/patches/patched/pew.patch +++ b/tasks/vendoring/patches/patched/pew.patch @@ -23,7 +23,7 @@ index d1d8e0a..c45c37e 100644 +try: + from pathlib import Path +except ImportError: -+ from pathlib2 import Path ++ from pipenv.vendor.pathlib2 import Path from tempfile import NamedTemporaryFile as _ntf try: from shutil import which @@ -39,7 +39,7 @@ index bcaabad..b8fc3e7 100644 +try: + from pathlib import Path +except ImportError: -+ from pathlib2 import Path ++ from pipenv.vendor.pathlib2 import Path try: from shutil import get_terminal_size diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 3a07d145..66ce8be7 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -10,6 +10,11 @@ from pipenv.vendor import requests from pipenv.vendor import six from pipenv.vendor import toml +try: + from pathlib import Path +except ImportError: + from pipenv.vendor.pathlib2 import Path + if six.PY2: class ResourceWarning(Warning): @@ -45,7 +50,7 @@ class _PipenvInstance(object): self.original_umask = os.umask(0o007) self.original_dir = os.path.abspath(os.curdir) self._path = TemporaryDirectory(suffix='-project', prefix='pipenv-') - self.path = self._path.name + self.path = str(Path(self._path.name).resolve()) # set file creation perms self.pipfile_path = None self.chdir = chdir