diff --git a/.azure-pipelines/steps/run-tests-linux.yml b/.azure-pipelines/steps/run-tests-linux.yml index 0298e4ad29..7d63d8122e 100644 --- a/.azure-pipelines/steps/run-tests-linux.yml +++ b/.azure-pipelines/steps/run-tests-linux.yml @@ -1,3 +1,6 @@ +parameters: + python_version: '' + steps: - script: | # Fix Git SSL errors @@ -9,7 +12,7 @@ steps: PY_EXE: $(PY_EXE) GIT_SSL_CAINFO: $(GIT_SSL_CAINFO) LANG: $(LANG) - PIP_PROCESS_DEPENDENCY_LINKS: $(PIP_PROCESS_DEPENDENCY_LINKS) - PIPENV_DEFAULT_PYTHON_VERSION: $(PIPENV_DEFAULT_PYTHON_VERSION) + PIP_PROCESS_DEPENDENCY_LINKS: '$(PIP_PROCESS_DEPENDENCY_LINKS)' + PIPENV_DEFAULT_PYTHON_VERSION: '${{ parameters.python_version }}' PYTHONWARNINGS: ignore:DEPRECATION PIPENV_NOSPIN: '1' diff --git a/.azure-pipelines/steps/run-tests-windows.yml b/.azure-pipelines/steps/run-tests-windows.yml index 5d854a9b49..21e7e49d04 100644 --- a/.azure-pipelines/steps/run-tests-windows.yml +++ b/.azure-pipelines/steps/run-tests-windows.yml @@ -1,3 +1,6 @@ +parameters: + python_version: '' + steps: - powershell: | subst T: "$env:TEMP" @@ -11,6 +14,6 @@ steps: pipenv run pytest -ra --ignore=pipenv\patched --ignore=pipenv\vendor --junitxml=test-results.xml tests displayName: Run integration tests env: - PIPENV_DEFAULT_PYTHON_VERSION: $(PIPENV_DEFAULT_PYTHON_VERSION) + PIPENV_DEFAULT_PYTHON_VERSION: '${{ parameters.python_version }}' PYTHONWARNINGS: 'ignore:DEPRECATION' PIPENV_NOSPIN: '1' diff --git a/.azure-pipelines/steps/run-tests.yml b/.azure-pipelines/steps/run-tests.yml index 7373fa579a..63972c48d6 100644 --- a/.azure-pipelines/steps/run-tests.yml +++ b/.azure-pipelines/steps/run-tests.yml @@ -9,18 +9,22 @@ steps: - template: install-dependencies.yml - script: | - echo '##vso[task.setvariable variable=PIPENV_DEFAULT_PYTHON_VERSION]$PYTHON_VERSION' + echo '##vso[task.setvariable variable=PIPENV_DEFAULT_PYTHON_VERSION]$(python.version)' env: PYTHON_VERSION: $(python.version) - template: create-virtualenv.yml parameters: - python.version: $(python.version) + python_version: $(python.version) - ${{ if eq(parameters.vmImage, 'windows-2019') }}: - template: run-tests-windows.yml + parameters: + python_version: $(python.version) - ${{ if ne(parameters.vmImage, 'windows-2019') }}: - template: run-tests-linux.yml + parameters: + python_version: $(python.version) - task: PublishTestResults@2 displayName: Publish Test Results diff --git a/.azure-pipelines/steps/run-vendor-scripts.yml b/.azure-pipelines/steps/run-vendor-scripts.yml index fae9c1d675..be10e263a0 100644 --- a/.azure-pipelines/steps/run-vendor-scripts.yml +++ b/.azure-pipelines/steps/run-vendor-scripts.yml @@ -1,3 +1,6 @@ +parameters: + python_version: '' + steps: - script: | python -m pip install --upgrade invoke requests parver bs4 vistir towncrier pip setuptools wheel --upgrade-strategy=eager @@ -7,6 +10,6 @@ steps: PY_EXE: $(PY_EXE) GIT_SSL_CAINFO: $(GIT_SSL_CAINFO) LANG: $(LANG) - PIPENV_DEFAULT_PYTHON_VERSION: $(PIPENV_DEFAULT_PYTHON_VERSION) + PIPENV_DEFAULT_PYTHON_VERSION: '${{ parameters.python_version }}' PYTHONWARNINGS: ignore:DEPRECATION PIPENV_NOSPIN: '1' diff --git a/Pipfile.lock b/Pipfile.lock index 416bfd7990..da7768f964 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -61,36 +61,20 @@ }, "babel": { "hashes": [ - "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", - "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" + "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", + "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.6.0" + "version": "==2.7.0" }, "backports.functools-lru-cache": { "hashes": [ "sha256:9d98697f088eb1b0fa451391f91afb5e3ebde16bbdb272819fd091151fda4f1a", "sha256:f0b0e4eba956de51238e17573b7087e852dfe9854afd2e9c873f73fc0ca0a6dd" ], - "markers": "python_version == '2.7'", + "markers": "python_version < '3'", "version": "==1.5" }, - "backports.shutil-get-terminal-size": { - "hashes": [ - "sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", - "sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" - ], - "markers": "python_version == '2.7'", - "version": "==1.0.0" - }, - "backports.weakref": { - "hashes": [ - "sha256:81bc9b51c0abc58edc76aefbbc68c62a787918ffe943a37947e162c3f8e19e82", - "sha256:bc4170a29915f8b22c9e7c4939701859650f2eb84184aee80da329ac0b9825c2" - ], - "markers": "python_version == '2.7'", - "version": "==1.0.post1" - }, "beautifulsoup4": { "hashes": [ "sha256:034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858", @@ -121,19 +105,6 @@ ], "version": "==0.0.1" }, - "cached-property": { - "hashes": [ - "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f", - "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504" - ], - "version": "==1.5.1" - }, - "cerberus": { - "hashes": [ - "sha256:0be48fc0dc84f83202a5309c0aa17cd5393e70731a1698a50d118b762fbe6875" - ], - "version": "==1.3.1" - }, "certifi": { "hashes": [ "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", @@ -168,14 +139,16 @@ "sha256:8be81d89d6e7b4c0d4e44bcc525845f6da25821de80cb5e06e7e0238a2899e32", "sha256:da60d0014fd8c55eb48c1c5354352e363e2d30bbf7057e5e171a468390184c75" ], - "markers": "python_version == '2.7'", + "markers": "python_version < '3'", "version": "==3.7.4" }, - "distlib": { + "contextlib2": { "hashes": [ - "sha256:ecb3d0e4f71d0fa7f38db6bcc276c7c9a1c6638a516d726495934a553eb3fbe0" + "sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", + "sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00" ], - "version": "==0.2.9.post0" + "markers": "python_version < '3'", + "version": "==0.5.5" }, "docutils": { "hashes": [ @@ -211,13 +184,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.6.0" }, - "first": { - "hashes": [ - "sha256:8d8e46e115ea8ac652c76123c0865e3ff18372aef6f03c22809ceefcea9dec86", - "sha256:ff285b08c55f8c97ce4ea7012743af2495c9f1291785f163722bd36f6af6d3bf" - ], - "version": "==2.0.2" - }, "flake8": { "hashes": [ "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", @@ -236,17 +202,17 @@ }, "flask": { "hashes": [ - "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", - "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" + "sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3", + "sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61" ], - "version": "==1.0.2" + "version": "==1.0.3" }, "funcsigs": { "hashes": [ "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" ], - "markers": "python_version < '3.3'", + "markers": "python_version < '3.0'", "version": "==1.0.2" }, "functools32": { @@ -280,6 +246,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, + "importlib-metadata": { + "hashes": [ + "sha256:027cfc6524613de726789072f95d2e4cc64dd1dee8096d42d13f2ead5bd302f5", + "sha256:0d05199e1f0b1a8707a1b9c46476d4a49807fb56cb1b0737db1d37feb42fe31d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.15" + }, "incremental": { "hashes": [ "sha256:717e12246dddf231a349175f48d74d93e2897244939173b01974ab6661406b9f", @@ -297,11 +271,11 @@ }, "isort": { "hashes": [ - "sha256:1349c6f7c2a0f7539f5f2ace51a9a8e4a37086ce4de6f78f5f53fb041d0a3cd5", - "sha256:f09911f6eb114e5592abe635aded8bf3d2c3144ebcfcaf81ee32e7af7b7d1870" + "sha256:c40744b6bc5162bbb39c1257fe298b7a393861d50978b565f3ccd9cb9de0182a", + "sha256:f57abacd059dc3bd666258d1efb0377510a89777fda3e3274e3c01f7c03ae22d" ], "index": "pypi", - "version": "==4.3.18" + "version": "==4.3.20" }, "itsdangerous": { "hashes": [ @@ -423,7 +397,7 @@ "sha256:25199318e8cc3c25dcb45cbe084cc061051336d5a9ea2a12448d3d8cb748f742", "sha256:5887121d7f7df3603bca2f710e7219f3eca0eb69e0b7cc6e0a022e155ac931a7" ], - "markers": "python_version < '3.5'", + "markers": "python_version < '3.6'", "version": "==2.3.3" }, "pbr": { @@ -433,21 +407,6 @@ ], "version": "==5.2.0" }, - "pep517": { - "hashes": [ - "sha256:43a7aa3902efd305a605c1028e4045968cd012831233ecab633a31d3ba4860a5", - "sha256:cb5ca55450b64e80744cd5c32f7d5b8928004042dfea50fdc3f96ad7f27cba96" - ], - "version": "==0.5.0" - }, - "pip-shims": { - "hashes": [ - "sha256:3bc24ec050a6b9eea35419467237e4f47eaf806dadc9999bf887355c377edea7", - "sha256:edb4cf3c509eab2f36b55c1ac1a59a4c485ccd537cc87934d74950880f641256" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.3.2" - }, "pipenv": { "editable": true, "extras": [ @@ -463,24 +422,13 @@ ], "version": "==1.5.0.1" }, - "plette": { - "extras": [ - "validation" - ], - "hashes": [ - "sha256:c0e3553c1e581d8423daccbd825789c6e7f29b7d9e00e5331b12e1642a1a26d3", - "sha256:dde5d525cf5f0cbad4d938c83b93db17887918daf63c13eafed257c4f61b07b4" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.2.2" - }, "pluggy": { "hashes": [ - "sha256:25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180", - "sha256:964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a" + "sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc", + "sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.11.0" + "version": "==0.12.0" }, "py": { "hashes": [ @@ -508,10 +456,11 @@ }, "pygments": { "hashes": [ - "sha256:5ffada19f6203563680669ee7f53b64dabbeb100eb51b61996085e99c03b284a", - "sha256:e8218dd399a61674745138520d0d4cf2621d7e032439341bc3f647bff125818d" + "sha256:36586500a94cd97f8c2c19d251cdb78868d1a822e0e491bfc1d811766aedb772", + "sha256:b437bc0d04dc36f1f5b3592985b3e0a3d0af46b7c39199231706d19a4ee63344" ], - "version": "==2.3.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.1" }, "pyparsing": { "hashes": [ @@ -555,12 +504,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.28.0" }, - "pytoml": { - "hashes": [ - "sha256:ca2d0cb127c938b8b76a9a0d0f855cf930c1d50cc3a0af6d3595b566519a1013" - ], - "version": "==0.1.20" - }, "pytz": { "hashes": [ "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", @@ -577,11 +520,11 @@ }, "requests": { "hashes": [ - "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e", - "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b" + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.21.0" + "version": "==2.22.0" }, "requests-toolbelt": { "hashes": [ @@ -590,21 +533,6 @@ ], "version": "==0.9.1" }, - "requirementslib": { - "hashes": [ - "sha256:a5bcff2861eea9358e90d6a4234f0bf4ad0ba730f86a4ea4680f53365b7b4735", - "sha256:ae0c2fce1b33c9c7b171895ab11472bd7be9c45f6214aad97ceaf83511d78d93" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.0" - }, - "resolvelib": { - "hashes": [ - "sha256:6c4c6690b0bdd78bcc002e1a5d1b6abbde58c694a6ea1838f165b20d2c943db7", - "sha256:8734e53271ef98f38a2c99324d5e7905bc00c97dc3fc5bb7d83c82a979e71c04" - ], - "version": "==0.2.2" - }, "rope": { "hashes": [ "sha256:6b728fdc3e98a83446c27a91fc5d56808a004f8beab7a31ab1d7224cecc7d969", @@ -671,17 +599,16 @@ }, "sphinxcontrib-websupport": { "hashes": [ - "sha256:4044751a075b6560f155c96f9fec6bc5198cd5307e5db9f77c7b1c5247ac9a09", - "sha256:c1b918b1b41cde045cdb9755941086b4ce4ebbfd7bff41d10ffb6d325779cbf9" + "sha256:1501befb0fdf1d1c29a800fdbf4ef5dc5369377300ddbdd16d2cd40e54c6eefc", + "sha256:e02f717baf02d0b6c3dd62cf81232ffca4c9d5c331e03766982e3ff9f1d2bc3f" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.1.1.dev20190321" + "version": "==1.1.2" }, "stdeb": { "hashes": [ "sha256:0ed2c2cc6b8ba21da7d646c6f37ca60b22e9e4950e3cec6bcd9c2e7e57e3747e" ], - "index": "pypi", "markers": "sys_platform == 'linux'", "version": "==0.8.5" }, @@ -700,14 +627,6 @@ ], "version": "==0.10.0" }, - "tomlkit": { - "hashes": [ - "sha256:d6506342615d051bc961f70bfcfa3d29b6616cc08a3ddfd4bc24196f16fd4ec2", - "sha256:f077456d35303e7908cc233b340f71e0bec96f63429997f38ca9272b7d64029e" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.5.3" - }, "towncrier": { "hashes": [ "sha256:48251a1ae66d2cf7e6fa5552016386831b3e12bb3b2d08eb70374508c17a8196", @@ -742,11 +661,11 @@ }, "urllib3": { "hashes": [ - "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4", - "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb" + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", - "version": "==1.24.3" + "version": "==1.25.3" }, "virtualenv": { "hashes": [ @@ -764,17 +683,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.5.3" }, - "vistir": { - "extras": [ - "spinner" - ], - "hashes": [ - "sha256:00af96b75157b299616f47657ed34368e92e01d039100368c9dcd94897e3c109", - "sha256:bbe040ce656f1de9b5f75c953abe49af4d1ba6fdf8f1f4b8db3e63cfd2dad24a" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.4.1" - }, "wcwidth": { "hashes": [ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", @@ -797,20 +705,13 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.15.4" }, - "wheel": { - "hashes": [ - "sha256:5e79117472686ac0c4aef5bad5172ea73a1c2d1646b808c35926bd26bdfb0c08", - "sha256:62fcfa03d45b5b722539ccbc07b190e4bfff4bb9e3a4d470dd9f6a0981002565" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.33.4" - }, - "yaspin": { + "zipp": { "hashes": [ - "sha256:8e6d2e2b207ba18510f190e04a25273a32d1f192af9c9a77ebe46deaca799dfa", - "sha256:94b7602f0dc59d26a15e63cefff6aaf644c58dd77fc4e1ef675d3ba2c302ed06" + "sha256:8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d", + "sha256:ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3" ], - "version": "==0.14.3" + "markers": "python_version >= '2.7'", + "version": "==0.5.1" } } } diff --git a/news/3577.feature.rst b/news/3577.feature.rst new file mode 100644 index 0000000000..7944c09878 --- /dev/null +++ b/news/3577.feature.rst @@ -0,0 +1 @@ +Added a new environment variable, ``PIPENV_RESOLVE_VCS``, to toggle dependency resolution off for non-editable VCS, file, and URL based dependencies. diff --git a/news/3647.bugfix.rst b/news/3647.bugfix.rst new file mode 100644 index 0000000000..cb64edc1bc --- /dev/null +++ b/news/3647.bugfix.rst @@ -0,0 +1 @@ +Pipenv will no longer inadvertently set ``editable=True`` on all vcs dependencies. diff --git a/news/3656.bugfix.rst b/news/3656.bugfix.rst new file mode 100644 index 0000000000..58df202019 --- /dev/null +++ b/news/3656.bugfix.rst @@ -0,0 +1,2 @@ +The ``--keep-outdated`` argument to ``pipenv install`` and ``pipenv lock`` will now drop specifier constraints when encountering editable dependencies. +- In addition, ``--keep-outdated`` will retain specifiers that would otherwise be dropped from any entries that have not been updated. diff --git a/pipenv/core.py b/pipenv/core.py index 7b00eb5916..9b4fa5a446 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1394,6 +1394,8 @@ def pip_install( src_dir = os.environ["PIP_SRC"] src = ["--src", os.environ["PIP_SRC"]] if not requirement.editable: + # Leave this off becauase old lockfiles don't have all deps included + # TODO: When can it be turned back on? no_deps = False if src_dir is not None: @@ -1412,7 +1414,7 @@ def pip_install( prefix="pipenv-", suffix="-requirement.txt", dir=requirements_dir, delete=False ) - line = "-e" if requirement.editable else "" + line = "-e " if requirement.editable else "" if requirement.editable or requirement.name is not None: name = requirement.name if requirement.extras: @@ -1640,7 +1642,6 @@ def system_which(command, mult=False): return result - def format_help(help): """Formats the help string.""" help = help.replace("Options:", str(crayons.normal("Options:", bold=True))) @@ -1784,8 +1785,8 @@ def do_py(system=False): ), err=True, ) - return - + return + try: click.echo(which("python", allow_global=system)) except AttributeError: diff --git a/pipenv/environments.py b/pipenv/environments.py index 34aef2bce7..e7e64d31a1 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -236,6 +236,15 @@ def _is_env_truthy(name): NOTE: This only affects the ``install`` and ``uninstall`` commands. """ +PIPENV_RESOLVE_VCS = _is_env_truthy(os.environ.get("PIPENV_RESOLVE_VCS", 'true')) +"""Tells Pipenv whether to resolve all VCS dependencies in full. + +As of Pipenv 2018.11.26, only editable VCS dependencies were resolved in full. +To retain this behavior and avoid handling any conflicts that arise from the new +approach, you may set this to '0', 'off', or 'false'. +""" + + PIPENV_PYUP_API_KEY = os.environ.get( "PIPENV_PYUP_API_KEY", "1ab8d58f-5122e025-83674263-bc1e79e0" ) diff --git a/pipenv/patched/piptools/utils.py b/pipenv/patched/piptools/utils.py index 88755431f7..fb846cc4a6 100644 --- a/pipenv/patched/piptools/utils.py +++ b/pipenv/patched/piptools/utils.py @@ -70,7 +70,7 @@ def clean_requires_python(candidates): all_candidates = [] py_version = parse_version(os.environ.get('PIP_PYTHON_VERSION', '.'.join(map(str, sys.version_info[:3])))) for c in candidates: - if c.requires_python: + if getattr(c, "requires_python", None): # Old specifications had people setting this to single digits # which is effectively the same as '>=digit, str return self.entry.specifiers @property @@ -373,7 +390,7 @@ def original_version(self): return None def validate_specifiers(self): - if self.is_in_pipfile: + if self.is_in_pipfile and not self.pipfile_entry.editable: return self.pipfile_entry.requirement.specifier.contains(self.updated_version) return True @@ -550,8 +567,11 @@ def validate_constraints(self): constraint.check_if_exists(False) except Exception: from pipenv.exceptions import DependencyConflict + from pipenv.environments import is_verbose + if is_verbose(): + print("Tried constraint: {0!r}".format(constraint), file=sys.stderr) msg = ( - "Cannot resolve conflicting version {0}{1} while {1}{2} is " + "Cannot resolve conflicting version {0}{1} while {2}{3} is " "locked.".format( self.name, self.updated_specifier, self.old_name, self.old_specifiers ) @@ -624,6 +644,7 @@ def clean_results(results, resolver, project, dev=False): def clean_outdated(results, resolver, project, dev=False): from pipenv.vendor.requirementslib.models.requirements import Requirement + from pipenv.environments import is_verbose if not project.lockfile_exists: return results lockfile = project.lockfile_content diff --git a/pipenv/utils.py b/pipenv/utils.py index b73b7fa737..b99c51e7d7 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -31,7 +31,9 @@ import parse from . import environments -from .exceptions import PipenvUsageError, ResolutionFailure, RequirementError, PipenvCmdError +from .exceptions import ( + PipenvUsageError, RequirementError, PipenvCmdError, ResolutionFailure +) from .pep508checker import lookup from .vendor.urllib3 import util as urllib3_util @@ -398,7 +400,6 @@ def parse_line( ): # type: (...) -> Tuple[Requirement, Dict[str, str], Dict[str, str]] from .vendor.requirementslib.models.requirements import Requirement - from .exceptions import ResolutionFailure if index_lookup is None: index_lookup = {} if markers_lookup is None: @@ -444,6 +445,7 @@ def get_deps_from_req(cls, req, resolver=None): # type: (Requirement, Optional["Resolver"]) -> Tuple[Set[str], Dict[str, Dict[str, Union[str, bool, List[str]]]]] from .vendor.requirementslib.models.utils import _requirement_to_str_lowercase_name from .vendor.requirementslib.models.requirements import Requirement + from requirementslib.utils import is_installable_dir constraints = set() # type: Set[str] locked_deps = dict() # type: Dict[str, Dict[str, Union[str, bool, List[str]]]] if (req.is_file_or_url or req.is_vcs) and not req.is_wheel: @@ -463,7 +465,16 @@ def get_deps_from_req(cls, req, resolver=None): setup_info = req.req.setup_info setup_info.get_info() locked_deps[pep423_name(name)] = entry - requirements = [v for v in getattr(setup_info, "requires", {}).values()] + requirements = [] + # Allow users to toggle resolution off for non-editable VCS packages + # but leave it on for local, installable folders on the filesystem + if environments.PIPENV_RESOLVE_VCS or ( + req.editable or parsed_line.is_wheel or ( + req.is_file_or_url and parsed_line.is_local and + is_installable_dir(parsed_line.path) + ) + ): + requirements = [v for v in getattr(setup_info, "requires", {}).values()] for r in requirements: if getattr(r, "url", None) and not getattr(r, "editable", False): if r is not None: @@ -1744,7 +1755,7 @@ def translate_markers(pipfile_entry): marker_set = set() if "markers" in new_pipfile: marker_str = new_pipfile.pop("markers") - if marker_str is not None: + if marker_str: marker = str(Marker(marker_str)) if 'extra' not in marker: marker_set.add(marker) @@ -1797,13 +1808,15 @@ def clean_resolved_dep(dep, is_top_level=False, pipfile_entry=None): # If a package is **PRESENT** in the pipfile but has no markers, make sure we # **NEVER** include markers in the lockfile - if "markers" in dep: + if "markers" in dep and dep.get("markers", "").strip(): # First, handle the case where there is no top level dependency in the pipfile if not is_top_level: - try: - lockfile["markers"] = translate_markers(dep)["markers"] - except TypeError: - pass + translated = translate_markers(dep).get("markers", "").strip() + if translated: + try: + lockfile["markers"] = translated + except TypeError: + pass # otherwise make sure we are prioritizing whatever the pipfile says about the markers # If the pipfile says nothing, then we should put nothing in the lockfile else: diff --git a/pipenv/vendor/vistir/compat.py b/pipenv/vendor/vistir/compat.py index a44aafbe44..ee96f761d0 100644 --- a/pipenv/vendor/vistir/compat.py +++ b/pipenv/vendor/vistir/compat.py @@ -87,10 +87,19 @@ 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""" - pass + def __init__(self, *args, **kwargs): + self.errno = errno.EISDIR + super(IsADirectoryError, self).__init__(*args, **kwargs) class FileExistsError(OSError): def __init__(self, *args, **kwargs): @@ -105,6 +114,7 @@ def __init__(self, *args, **kwargs): PermissionError, IsADirectoryError, FileExistsError, + TimeoutError, ) from io import StringIO diff --git a/pipenv/vendor/vistir/misc.py b/pipenv/vendor/vistir/misc.py index 8d58aad63e..e46700e54e 100644 --- a/pipenv/vendor/vistir/misc.py +++ b/pipenv/vendor/vistir/misc.py @@ -20,6 +20,7 @@ Iterable, Path, StringIO, + TimeoutError, fs_str, is_bytes, partialmethod, @@ -185,6 +186,7 @@ def _read_streams(stream_dict): return results + def get_stream_results(cmd_instance, verbose, maxlen, spinner=None, stdout_allowed=False): stream_results = {"stdout": [], "stderr": []} streams = {"stderr": cmd_instance.stderr, "stdout": cmd_instance.stdout} @@ -194,11 +196,22 @@ def get_stream_results(cmd_instance, verbose, maxlen, spinner=None, stdout_allow stderr_line = stream_contents["stderr"] if not (stdout_line or stderr_line): break + last_changed = 0 + display_line = "" for stream_name in stream_contents.keys(): if stream_contents[stream_name] and stream_name in stream_results: line = stream_contents[stream_name] stream_results[stream_name].append(line) - display_line = fs_str("{0}".format(line)) + display_line = ( + fs_str("{0}".format(line)) + if stream_name == "stderr" + else display_line + ) + if display_line and last_changed < 100: + last_changed = 0 + display_line = "" + elif display_line: + last_changed += 1 if len(display_line) > maxlen: display_line = "{0}...".format(display_line[:maxlen]) if verbose: @@ -371,7 +384,7 @@ def run( spinner=sp, combine_stderr=combine_stderr, start_text=start_text, - write_to_stdout=True, + write_to_stdout=write_to_stdout, ) diff --git a/tasks/vendoring/patches/patched/piptools.patch b/tasks/vendoring/patches/patched/piptools.patch index 14c3354ce1..c220eb4bed 100644 --- a/tasks/vendoring/patches/patched/piptools.patch +++ b/tasks/vendoring/patches/patched/piptools.patch @@ -608,7 +608,7 @@ index 9b4b4c2..8875543 100644 + all_candidates = [] + py_version = parse_version(os.environ.get('PIP_PYTHON_VERSION', '.'.join(map(str, sys.version_info[:3])))) + for c in candidates: -+ if c.requires_python: ++ if getattr(c, "requires_python", None): + # Old specifications had people setting this to single digits + # which is effectively the same as '>=digit,= '2.7'" + + @pytest.mark.lock @pytest.mark.keep_outdated def test_keep_outdated_doesnt_update_satisfied_constraints(PipenvInstance, pypi):