diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 371959e2..bc3e47f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: exclude: .patch - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.285 + rev: v0.0.286 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a64395c5..613dd4f9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,25 @@ +2023.9.1 (2023-09-01) +===================== +Pipenv 2023.9.1 (2023-09-01) +============================ + + +Features & Improvements +----------------------- + +- Top level Pipfile sys_platform markers should be transitive; adds top level platform_machine entries that are also transitive. Marker entries continue to operate the same as before. `#5892 `_ + +Bug Fixes +--------- + +- Apply patch for install_search_all_sources = True functionality. `#5895 `_ +- Relative paths improvements for editable installs. `#5896 `_ +- Set log level in resolver to WARN when verbose is not passed. `#5897 `_ +- Handle more variations in private index html to improve hash collection. `#5898 `_ + + 2023.8.28 (2023-08-28) ====================== -Pipenv 2023.8.28 (2023-08-28) -============================= - Bug Fixes --------- @@ -14,9 +31,6 @@ Bug Fixes 2023.8.26 (2023-08-26) ====================== -Pipenv 2023.8.26 (2023-08-26) -============================= - Bug Fixes --------- @@ -29,9 +43,6 @@ Bug Fixes 2023.8.25 (2023-08-25) ====================== -Pipenv 2023.8.25 (2023-08-25) -============================= - Bug Fixes --------- @@ -434,8 +445,8 @@ Vendored Libraries - Vendor in ``pip==22.3.1`` which is currently the latest version of ``pip``. `#5520 `_ - * Bump version of requirementslib to 2.2.1 - * Bump version of vistir to 0.7.5 - * Bump version of colorama to 0.4.6 `#5522 `_ + * Bump version of vistir to 0.7.5 + * Bump version of colorama to 0.4.6 `#5522 `_ - Bump plette version to 0.4.4 `#5539 `_ @@ -482,9 +493,9 @@ Vendored Libraries ------------------ - * Drop unused code from cerberus - * Drop unused module wheel `#5467 `_ + * Drop unused module wheel `#5467 `_ - * Replace yaspin spinner with rich spinner. - * Bump vistir version to 0.7.4 `#5468 `_ + * Bump vistir version to 0.7.4 `#5468 `_ - Bump version of requirementslib to 2.2.0 Drop yaspin which is no longer used. Bump vistir to version 0.7.4 @@ -886,11 +897,10 @@ Vendored Libraries ------------------ - * Rename patched ``notpip`` to ``pip`` in order to be clear that its a patched version of pip. - * Remove the part of _post_pip_import.patch that overrode the standalone pip to be the user installed pip, - now we fully rely on our vendored and patched ``pip``, even for all types of installs. + * Remove the part of _post_pip_import.patch that overrode the standalone pip to be the user installed pip, now we fully rely on our vendored and patched ``pip``, even for all types of installs. * Vendor in the next newest version of ``pip==22.2`` * Modify patch for ``pipdeptree`` to not use ``pip-shims`` `#5188 `_ -- * Remove vendored ``urllib3`` in favor of using it from vendored version in ``pip._vendor`` `#5215 `_ + * Remove vendored ``urllib3`` in favor of using it from vendored version in ``pip._vendor`` `#5215 `_ Removals and Deprecations ------------------------- @@ -1605,11 +1615,11 @@ Vendored Libraries - Update vendored dependencies and invocations - Update vendored and patched dependencies - - Update patches on ``piptools``, ``pip``, ``pip-shims``, ``tomlkit` + - Update patches on ``piptools``, ``pip``, ``pip-shims``, ``tomlkit`` - Fix invocations of dependencies - - Fix custom ``InstallCommand` instantiation - - Update ``PackageFinder` usage - - Fix ``Bool` stringify attempts from ``tomlkit` + - Fix custom ``InstallCommand`` instantiation + - Update ``PackageFinder`` usage + - Fix ``Bool`` stringify attempts from ``tomlkit`` Updated vendored dependencies: - **attrs**: ```18.2.0`` => ```19.1.0`` @@ -1992,7 +2002,9 @@ Bug Fixes - ``requirementslib 1.1.16 => 1.1.17`` - ``shellingham 1.2.4 => 1.2.6`` - ``tomlkit 0.4.2 => 0.4.4`` - - ``vistir 0.1.4 => 0.1.6`` `#2802 `_, + - ``vistir 0.1.4 => 0.1.6`` + + `#2802 `_, `#2867 `_, `#2880 `_ @@ -2046,7 +2058,9 @@ Vendored Libraries - ``requirementslib 1.1.16 => 1.1.17`` - ``shellingham 1.2.4 => 1.2.6`` - ``tomlkit 0.4.2 => 0.4.4`` - - ``vistir 0.1.4 => 0.1.6`` `#2902 `_, + - ``vistir 0.1.4 => 0.1.6`` + + `#2902 `_, `#2935 `_ diff --git a/Pipfile b/Pipfile index 67e0637e..8c1b89f5 100644 --- a/Pipfile +++ b/Pipfile @@ -10,22 +10,27 @@ sphinx-click = "==4.*" sphinxcontrib-spelling = "==7.*" click = "==8.0.3" pypiserver = "==1.*" -stdeb = {version="*", markers="sys_platform == 'linux'"} +stdeb = {version="*", sys_platform = "== 'linux'"} zipp = {version = "==3.6.0", markers = "python_version < '3.10'"} pre-commit = "==2.*" -atomicwrites = {version = "*", markers="sys_platform == 'win32'"} +atomicwrites = {version = "*", sys_platform = "== 'win32'"} pytest-cov = "==3.*" +pluggy = "==1.2.0" # Can be removed from Pipfile when dropping py 3.7 +filelock = "==3.12.2" # Can be removed from Pipfile when dropping py 3.7 +coverage = "==7.2.7" # Can be removed from Pipfile when dropping py 3.7 typing-extensions = "==4.*" -waitress = {version = "*", markers="sys_platform == 'win32'"} -gunicorn = {version = "*", markers="sys_platform == 'linux'"} +waitress = {version = "*", sys_platform = "== 'win32'"} +gunicorn = {version = "*", sys_platform = "== 'linux'"} parse = "*" -importlib-metadata = {version = "*", markers="python_version < '3.8'"} -colorama= {version = "*", markers="sys_platform == 'win32'"} +importlib-metadata = {version = "*"} +colorama= {version = "*", sys_platform = "== 'win32'"} myst-parser = {extras = ["linkify"], version = "*"} invoke = "==2.0.0" exceptiongroup = "==1.1.0" tomli = "*" pyyaml = "==6.0.1" +build = "*" +twine = "*" [packages] pytz = "*" diff --git a/Pipfile.lock b/Pipfile.lock index a50d34de..b5b49571 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8a01aed3d68063b2b3880a1bbbb8113abeeb21fddea18c6d68dbc40f594d9c54" + "sha256": "8a84150804ee1b1aa65d180190c3795476aea5d3a49b530663ce52a03b5ca8c1" }, "pipfile-spec": 6, "requires": {}, @@ -43,7 +43,6 @@ "hashes": [ "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11" ], - "markers": "sys_platform == 'win32'", "version": "==1.4.1" }, "attrs": { @@ -67,7 +66,6 @@ "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" ], - "markers": "python_full_version >= '3.6.0'", "version": "==4.12.2" }, "black": { @@ -98,9 +96,25 @@ "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4", "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3" ], - "markers": "python_version >= '3.7'", "version": "==23.3.0" }, + "bleach": { + "hashes": [ + "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414", + "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4" + ], + "markers": "python_version >= '3.7'", + "version": "==6.0.0" + }, + "build": { + "hashes": [ + "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171", + "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.10.0" + }, "certifi": { "hashes": [ "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", @@ -220,13 +234,10 @@ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], - "markers": "sys_platform == 'win32'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' and sys_platform == 'win32'", "version": "==0.4.6" }, "coverage": { - "extras": [ - "toml" - ], "hashes": [ "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f", "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2", @@ -289,6 +300,7 @@ "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850", "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3" ], + "index": "pypi", "markers": "python_version >= '3.7'", "version": "==7.2.7" }, @@ -329,6 +341,7 @@ "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81", "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec" ], + "index": "pypi", "markers": "python_version >= '3.7'", "version": "==3.12.2" }, @@ -337,7 +350,6 @@ "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b", "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==3.9.2" }, "flaky": { @@ -345,24 +357,23 @@ "sha256:3ad100780721a1911f57a165809b7ea265a7863305acb66708220820caf8aa0d", "sha256:d6eda73cab5ae7364504b7c44670f70abed9e75f77dd116352f662817592ec9c" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==3.7.0" }, "gunicorn": { "hashes": [ - "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e", - "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8" + "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0", + "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033" ], - "markers": "sys_platform == 'linux'", - "version": "==20.1.0" + "markers": "python_version >= '3.5' and sys_platform == 'linux'", + "version": "==21.2.0" }, "identify": { "hashes": [ - "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f", - "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54" + "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4", + "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d" ], - "markers": "python_version >= '3.8'", - "version": "==2.5.26" + "markers": "python_version >= '3.7'", + "version": "==2.5.24" }, "idna": { "hashes": [ @@ -382,11 +393,19 @@ }, "importlib-metadata": { "hashes": [ - "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad", - "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d" + "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", + "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5" ], - "markers": "python_version < '3.8'", - "version": "==6.0.0" + "markers": "python_version >= '3.7'", + "version": "==6.7.0" + }, + "importlib-resources": { + "hashes": [ + "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6", + "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a" + ], + "markers": "python_version < '3.9'", + "version": "==5.12.0" }, "incremental": { "hashes": [ @@ -412,6 +431,14 @@ "markers": "python_version >= '3.6'", "version": "==2.0.0" }, + "jaraco.classes": { + "hashes": [ + "sha256:2353de3288bc6b82120752201c6b1c1a14b058267fa424ed5ce5984e3b922158", + "sha256:89559fa5c1d3c34eff6f631ad80bb21f378dbcbb35dd161fd2c6b93f5be2f98a" + ], + "markers": "python_version >= '3.7'", + "version": "==3.2.3" + }, "jinja2": { "hashes": [ "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", @@ -420,6 +447,14 @@ "markers": "python_version >= '3.7'", "version": "==3.1.2" }, + "keyring": { + "hashes": [ + "sha256:3d44a48fa9a254f6c72879d7c88604831ebdaac6ecb0b214308b02953502c510", + "sha256:bc402c5e501053098bcbd149c4ddbf8e36c6809e572c2d098d4961e88d4c270d" + ], + "markers": "python_version >= '3.7'", + "version": "==24.1.1" + }, "linkify-it-py": { "hashes": [ "sha256:11e29f00150cddaa8f434153f103c14716e7e097a8fd372d9eb1ed06ed91524d", @@ -519,9 +554,16 @@ "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744", "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d" ], - "markers": "python_version >= '3.6'", "version": "==5.1.0" }, + "more-itertools": { + "hashes": [ + "sha256:cabaa341ad0389ea83c17a94566a53ae4c9d07349861ecb14dc6d0345cf9ac5d", + "sha256:d2bc7f02446e86a68911e58ded76d6561eea00cddfb2a91e7019bbb586c799f3" + ], + "markers": "python_version >= '3.7'", + "version": "==9.1.0" + }, "mypy-extensions": { "hashes": [ "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", @@ -570,7 +612,6 @@ "sha256:c66d3347a4858643875ef959d8ba7a269d5964bfb690b0dd998b8f39da930be2", "sha256:d4a3dbb93c53373ee9a0ba055e4858c44169b204b912e49d003ead95db9a9bca" ], - "markers": "python_version >= '3.7'", "version": "==0.4" }, "pathspec": { @@ -597,6 +638,14 @@ ], "path": "." }, + "pkginfo": { + "hashes": [ + "sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546", + "sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046" + ], + "markers": "python_version >= '3.6'", + "version": "==1.9.6" + }, "platformdirs": { "hashes": [ "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d", @@ -610,6 +659,7 @@ "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" ], + "index": "pypi", "markers": "python_version >= '3.7'", "version": "==1.2.0" }, @@ -650,11 +700,11 @@ }, "pygments": { "hashes": [ - "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", - "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" + "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692", + "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29" ], "markers": "python_version >= '3.7'", - "version": "==2.15.1" + "version": "==2.16.1" }, "pypiserver": { "hashes": [ @@ -665,6 +715,14 @@ "markers": "python_version >= '3.6'", "version": "==1.5.2" }, + "pyproject-hooks": { + "hashes": [ + "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8", + "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.0" + }, "pytest": { "hashes": [ "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", @@ -687,7 +745,6 @@ "sha256:c07ca07404c612f8abbe22294b23c368e2e5104b521c1790195561f37e1ac3d9", "sha256:f6f50101443ce70ad325ceb4473c4255e9d74e3c7cd0ef827309dfa4c0d975c6" ], - "markers": "python_version >= '3.6'", "version": "==2.1.0" }, "pytest-xdist": { @@ -695,12 +752,29 @@ "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93", "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2" ], - "markers": "python_version >= '3.7'", "version": "==3.3.1" }, + "pytz": { + "hashes": [ + "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" + ], + "index": "pypi", + "version": "==2023.3" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60", + "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.2.2" + }, "pyyaml": { "hashes": [ + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", @@ -708,7 +782,10 @@ "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", @@ -716,9 +793,12 @@ "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", @@ -733,7 +813,9 @@ "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", @@ -745,6 +827,14 @@ "markers": "python_version >= '3.6'", "version": "==6.0.1" }, + "readme-renderer": { + "hashes": [ + "sha256:cd653186dfc73055656f090f227f5cb22a046d7f71a841dfa305f55c9a513273", + "sha256:f67a16caedfa71eef48a31b39708637a6f4664c4394801a7b0d6432d13907343" + ], + "markers": "python_version >= '3.7'", + "version": "==37.3" + }, "requests": { "hashes": [ "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", @@ -753,6 +843,30 @@ "markers": "python_version >= '3.7'", "version": "==2.31.0" }, + "requests-toolbelt": { + "hashes": [ + "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", + "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.0.0" + }, + "rfc3986": { + "hashes": [ + "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "rich": { + "hashes": [ + "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808", + "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==13.5.2" + }, "setuptools": { "hashes": [ "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", @@ -761,6 +875,14 @@ "markers": "python_version >= '3.7'", "version": "==68.0.0" }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, "snowballstemmer": { "hashes": [ "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", @@ -796,11 +918,11 @@ }, "sphinxcontrib-applehelp": { "hashes": [ - "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228", - "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e" + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" ], - "markers": "python_version >= '3.8'", - "version": "==1.0.4" + "markers": "python_version >= '3.5'", + "version": "==1.0.2" }, "sphinxcontrib-devhelp": { "hashes": [ @@ -812,11 +934,11 @@ }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff", - "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903" + "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07", + "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2" ], - "markers": "python_version >= '3.8'", - "version": "==2.0.1" + "markers": "python_version >= '3.6'", + "version": "==2.0.0" }, "sphinxcontrib-jsmath": { "hashes": [ @@ -855,7 +977,6 @@ "hashes": [ "sha256:08c22c9c03b28a140fe3ec5064b53a5288279f22e596ca06b0be698d50c93cf2" ], - "markers": "sys_platform == 'linux'", "version": "==0.10.0" }, "tomli": { @@ -872,9 +993,64 @@ "sha256:da552f29192b3c2b04d630133f194c98e9f14f0558669d427708e203fea4d0a5", "sha256:fc29bd5ab4727c8dacfbe636f7fb5dc53b99805b62da1c96b214836159ff70c1" ], - "markers": "python_version >= '3.7'", "version": "==23.6.0" }, + "twine": { + "hashes": [ + "sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8", + "sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==4.0.2" + }, + "typed-ast": { + "hashes": [ + "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10", + "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede", + "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e", + "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c", + "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d", + "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8", + "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e", + "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5", + "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155", + "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4", + "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba", + "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5", + "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a", + "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b", + "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311", + "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769", + "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686", + "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d", + "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2", + "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814", + "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9", + "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b", + "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b", + "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4", + "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd", + "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18", + "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa", + "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6", + "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee", + "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88", + "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4", + "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431", + "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04", + "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d", + "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02", + "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8", + "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437", + "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274", + "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f", + "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a", + "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2" + ], + "markers": "python_version < '3.8' and implementation_name == 'cpython'", + "version": "==1.5.5" + }, "typing-extensions": { "hashes": [ "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", @@ -902,20 +1078,27 @@ }, "virtualenv": { "hashes": [ - "sha256:43a3052be36080548bdee0b42919c88072037d50d56c28bd3f853cbe92b953ff", - "sha256:fd8a78f46f6b99a67b7ec5cf73f92357891a7b3a40fd97637c27f854aae3b9e0" + "sha256:29c70bb9b88510f6414ac3e55c8b413a1f96239b6b789ca123437d5e892190cb", + "sha256:772b05bfda7ed3b8ecd16021ca9716273ad9f4467c801f27e83ac73430246dca" ], "markers": "python_version >= '3.7'", - "version": "==20.24.2" + "version": "==20.24.4" }, "waitress": { "hashes": [ "sha256:7500c9625927c8ec60f54377d590f67b30c8e70ef4b8894214ac6e4cad233d2a", "sha256:780a4082c5fbc0fde6a2fcfe5e26e6efc1e8f425730863c04085769781f51eba" ], - "markers": "sys_platform == 'win32'", + "markers": "python_full_version >= '3.7.0' and sys_platform == 'win32'", "version": "==2.1.2" }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, "zipp": { "hashes": [ "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832", diff --git a/pipenv/__version__.py b/pipenv/__version__.py index 529af700..c8960a6e 100644 --- a/pipenv/__version__.py +++ b/pipenv/__version__.py @@ -2,4 +2,4 @@ # // ) ) / / // ) ) //___) ) // ) ) || / / # //___/ / / / //___/ / // // / / || / / # // / / // ((____ // / / ||/ / -__version__ = "2023.8.29.dev0" +__version__ = "2023.9.2.dev0" diff --git a/pipenv/cli/options.py b/pipenv/cli/options.py index 78c30d2d..701cf9ed 100644 --- a/pipenv/cli/options.py +++ b/pipenv/cli/options.py @@ -502,6 +502,7 @@ def skip_lock_option(f): default=False, expose_value=True, envvar="PIPENV_SKIP_LOCK", + help="Install from Pipfile bypassing lock mechanisms.", callback=callback, type=click_types.BOOL, show_envvar=True, diff --git a/pipenv/environment.py b/pipenv/environment.py index 4187ba13..26b42e66 100644 --- a/pipenv/environment.py +++ b/pipenv/environment.py @@ -525,7 +525,7 @@ class Environment: if not loc.exists(): continue for pth in loc.iterdir(): - if not pth.suffix == ".egg-link": + if pth.suffix != ".egg-link": continue contents = [ normalize_path(line.strip()) for line in pth.read_text().splitlines() @@ -688,10 +688,10 @@ class Environment: tree = PackageDAG.from_pkgs(packages).sort() branch_keys = {r.key for r in flatten(tree.values())} - if pkg is not None: - nodes = [p for p in tree.keys() if p.key == pkg] + if pkg is None: + nodes = [p for p in tree if p.key not in branch_keys] else: - nodes = [p for p in tree.keys() if p.key not in branch_keys] + nodes = [p for p in tree if p.key == pkg] key_tree = {k.key: v for k, v in tree.items()} return [self._get_requirements_for_package(p, key_tree) for p in nodes] diff --git a/pipenv/environments.py b/pipenv/environments.py index fea1fd7f..325b63ac 100644 --- a/pipenv/environments.py +++ b/pipenv/environments.py @@ -222,7 +222,7 @@ class Setting: _spinners.SPINNERS[None] = {"interval": 80, "frames": " "} self.PIPENV_SPINNER = None else: - pipenv_spinner = "dots" if not os.name == "nt" else "bouncingBar" + pipenv_spinner = "bouncingBar" if os.name == "nt" else "dots" self.PIPENV_SPINNER = get_from_env( "SPINNER", check_for_negation=False, default=pipenv_spinner ) @@ -293,7 +293,7 @@ class Setting: """ When set True, will create or use the ``.venv`` in your project directory. When Set False, will ignore the .venv in your project directory even if it exists. If unset (default), will use the .venv of project directory should it exist, otherwise - will create new virtual environments in a global location. + will create new virtual environments in a global location. """ self.PIPENV_VERBOSE = bool(get_from_env("VERBOSE", check_for_negation=False)) @@ -397,10 +397,10 @@ class Setting: del self.PIPENV_VERBOSE def is_verbose(self, threshold=1): - return self.PIPENV_VERBOSITY >= threshold + return threshold <= self.PIPENV_VERBOSITY def is_quiet(self, threshold=-1): - return self.PIPENV_VERBOSITY <= threshold + return threshold >= self.PIPENV_VERBOSITY def is_using_venv() -> bool: diff --git a/pipenv/patched/pip/_internal/models/search_scope.py b/pipenv/patched/pip/_internal/models/search_scope.py index 85b35f7f..a3d9929c 100644 --- a/pipenv/patched/pip/_internal/models/search_scope.py +++ b/pipenv/patched/pip/_internal/models/search_scope.py @@ -20,7 +20,7 @@ class SearchScope: Encapsulates the locations that pip is configured to search. """ - __slots__ = ["find_links", "index_urls", "no_index", "index_lookup"] + __slots__ = ["find_links", "index_urls", "no_index", "index_lookup", "index_restricted"] @classmethod def create( @@ -29,6 +29,7 @@ class SearchScope: index_urls: List[str], no_index: bool, index_lookup: Optional[Dict[str, List[str]]] = None, + index_restricted: bool = False, ) -> "SearchScope": """ Create a SearchScope object after normalizing the `find_links`. @@ -64,6 +65,7 @@ class SearchScope: index_urls=index_urls, no_index=no_index, index_lookup=index_lookup, + index_restricted=index_restricted, ) def __init__( @@ -72,11 +74,13 @@ class SearchScope: index_urls: List[str], no_index: bool, index_lookup: Optional[Dict[str, List[str]]] = None, + index_restricted: bool = False, ) -> None: self.find_links = find_links self.index_urls = index_urls self.no_index = no_index self.index_lookup = index_lookup if index_lookup else {} + self.index_restricted = index_restricted def get_formatted_locations(self) -> str: lines = [] @@ -136,6 +140,6 @@ class SearchScope: index_urls = self.index_urls if project_name in self.index_lookup: index_urls = [self.index_lookup[project_name]] - elif self.index_urls: + elif self.index_restricted and self.index_urls: index_urls = [self.index_urls[0]] return [mkurl_pypi_url(url) for url in index_urls] diff --git a/pipenv/patched/pip/_vendor/certifi/cacert.pem b/pipenv/patched/pip/_vendor/certifi/cacert.pem index 5183934b..7fd6b96a 100644 --- a/pipenv/patched/pip/_vendor/certifi/cacert.pem +++ b/pipenv/patched/pip/_vendor/certifi/cacert.pem @@ -1676,49 +1676,6 @@ HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Label: "E-Tugra Certification Authority" -# Serial: 7667447206703254355 -# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 -# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 -# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC -aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV -BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 -Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz -MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ -BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp -em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY -B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH -D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF -Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo -q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D -k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH -fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut -dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM -ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 -zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX -U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 -Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 -XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF -Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR -HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY -GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c -77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 -+GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK -vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 -FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl -yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P -AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD -y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d -NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- # Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center @@ -4397,72 +4354,6 @@ ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- -# Issuer: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Subject: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Label: "E-Tugra Global Root CA RSA v3" -# Serial: 75951268308633135324246244059508261641472512052 -# MD5 Fingerprint: 22:be:10:f6:c2:f8:03:88:73:5f:33:29:47:28:47:a4 -# SHA1 Fingerprint: e9:a8:5d:22:14:52:1c:5b:aa:0a:b4:be:24:6a:23:8a:c9:ba:e2:a9 -# SHA256 Fingerprint: ef:66:b0:b1:0a:3c:db:9f:2e:36:48:c7:6b:d2:af:18:ea:d2:bf:e6:f1:17:65:5e:28:c4:06:0d:a1:a3:f4:c2 ------BEGIN CERTIFICATE----- -MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQEL -BQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUt -VHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYw -JAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgw -OTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMG -QW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 -Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBD -QSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J7 -7gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscx -uj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd8 -7jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/ -rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFL -l+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bG -wzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4 -znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBO -M/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK -5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAH -nnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2Amo -DVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSy -tK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL -BQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ -6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18 -Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ -3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPk -vmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn9 -9t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQ -mhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YA -VSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF -9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscM -moi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8 -bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ ------END CERTIFICATE----- - -# Issuer: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Subject: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Label: "E-Tugra Global Root CA ECC v3" -# Serial: 218504919822255052842371958738296604628416471745 -# MD5 Fingerprint: 46:bc:81:bb:f1:b5:1e:f7:4b:96:bc:14:e2:e7:27:64 -# SHA1 Fingerprint: 8a:2f:af:57:53:b1:b0:e6:a1:04:ec:5b:6a:69:71:6d:f6:1c:e2:84 -# SHA256 Fingerprint: 87:3f:46:85:fa:7f:56:36:25:25:2e:6d:36:bc:d7:f1:6f:c2:49:51:f2:64:e4:7e:1b:95:4f:49:08:cd:ca:13 ------BEGIN CERTIFICATE----- -MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw -gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn -cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD -VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2 -NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r -YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh -IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF -Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ -KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK -fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB -Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C -MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp -ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6 -7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx -vmjkI6TZraE3 ------END CERTIFICATE----- # Issuer: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. # Subject: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. diff --git a/pipenv/project.py b/pipenv/project.py index deabaa3c..7a8978f0 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -21,6 +21,8 @@ try: except ImportError: from pipenv.vendor import tomli as toml +import contextlib + from pipenv.cmdparse import Script from pipenv.environment import Environment from pipenv.environments import Setting, is_in_virtualenv, normalize_pipfile_path @@ -208,10 +210,8 @@ class Project: # Hack to skip this during pipenv run, or -r. if ("run" not in sys.argv) and chdir: - try: + with contextlib.suppress(TypeError, AttributeError): os.chdir(self.project_directory) - except (TypeError, AttributeError): - pass def path_to(self, p: str) -> str: """Returns the absolute path to a given relative path.""" @@ -292,17 +292,16 @@ class Project: return None def get_hashes_from_remote_index_urls(self, ireq, source): - pkg_url = f"{source['url']}/{ireq.name}/" + normalized_name = normalize_name(ireq.name) + url_name = normalized_name.replace(".", "-") + pkg_url = f"{source['url']}/{url_name}/" session = self.get_requests_session_for_source(source) + try: collected_hashes = set() - # Grab the hashes from the new warehouse API. response = session.get(pkg_url, timeout=10) - # Create an instance of the parser parser = PackageIndexHTMLParser() - # Feed the HTML to the parser parser.feed(response.text) - # Extract hrefs hrefs = parser.urls version = "" @@ -310,19 +309,45 @@ class Project: spec = next(iter(s for s in ireq.specifier), None) if spec: version = spec.version + + # We'll check if the href looks like a version-specific page (i.e., ends with '/') for package_url in hrefs: - if version in parse.unquote(package_url): + parsed_url = parse.urlparse(package_url) + if version in parsed_url.path and parsed_url.path.endswith("/"): + # This might be a version-specific page. Fetch and parse it + version_url = urljoin(pkg_url, package_url) + version_response = session.get(version_url, timeout=10) + version_parser = PackageIndexHTMLParser() + version_parser.feed(version_response.text) + version_hrefs = version_parser.urls + + # Process these new hrefs as potential wheels + for v_package_url in version_hrefs: + url_params = parse.urlparse(v_package_url).fragment + params_dict = parse.parse_qs(url_params) + if params_dict.get(FAVORITE_HASH): + collected_hashes.add(params_dict[FAVORITE_HASH][0]) + else: # Fallback to downloading the file to obtain hash + v_package_full_url = urljoin(version_url, v_package_url) + link = Link(v_package_full_url) + file_hash = self.get_file_hash(session, link) + if file_hash: + collected_hashes.add(file_hash) + elif version in parse.unquote(package_url): + # Process the current href as a potential wheel from the main page url_params = parse.urlparse(package_url).fragment params_dict = parse.parse_qs(url_params) if params_dict.get(FAVORITE_HASH): collected_hashes.add(params_dict[FAVORITE_HASH][0]) else: # Fallback to downloading the file to obtain hash - package_url = urljoin(source["url"], package_url) - link = Link(package_url) + package_full_url = urljoin(pkg_url, package_url) + link = Link(package_full_url) file_hash = self.get_file_hash(session, link) if file_hash: collected_hashes.add(file_hash) + return self.prepend_hash_types(collected_hashes, FAVORITE_HASH) + except (ValueError, KeyError, ConnectionError): if self.s.is_verbose(): click.echo( @@ -1079,7 +1104,7 @@ class Project: if section is None: section = {} package_name = pep423_name(package_name) - for name in section.keys(): + for name in section: if pep423_name(name) == package_name: return name return None @@ -1198,8 +1223,12 @@ class Project: return newly_added, category, normalized_name def src_name_from_url(self, index_url): - name, _, tld_guess = urllib.parse.urlsplit(index_url).netloc.rpartition(".") - src_name = name.replace(".", "") + location = urllib.parse.urlsplit(index_url).netloc + if "." in location: + name, _, tld_guess = location.rpartition(".") + else: + name = location + src_name = name.replace(".", "").replace(":", "") try: self.get_source(name=src_name) except SourceNotFound: @@ -1218,11 +1247,10 @@ class Project: try: source = self.get_source(url=index) except SourceNotFound: - try: + with contextlib.suppress(SourceNotFound): source = self.get_source(name=index) - except SourceNotFound: - pass - if source is not None: + + if source is not None and source.get("name"): return source["name"] source = {"url": index, "verify_ssl": verify_ssl} source["name"] = self.src_name_from_url(index) @@ -1312,7 +1340,7 @@ class Project: """ # Casing for section. changed_values = False - unknown_names = [k for k in section.keys() if k not in set(self.proper_names)] + unknown_names = [k for k in section if k not in set(self.proper_names)] # Replace each package with proper casing. for dep in unknown_names: try: diff --git a/pipenv/resolver.py b/pipenv/resolver.py index 7a499a46..82e01ca3 100644 --- a/pipenv/resolver.py +++ b/pipenv/resolver.py @@ -1,5 +1,6 @@ import importlib.util import json +import logging import os import sys @@ -286,7 +287,7 @@ class Entry: @property def is_in_pipfile(self): - return True if self.pipfile_name else False + return bool(self.pipfile_name) @property def pipfile_packages(self): @@ -315,7 +316,7 @@ class Entry: def clean_specifier(specifier): from pipenv.patched.pip._vendor.packaging.specifiers import Specifier - if not any(specifier.startswith(k) for k in Specifier._operators.keys()): + if not any(specifier.startswith(k) for k in Specifier._operators): if specifier.strip().lower() in ["any", "", "*"]: return "*" specifier = f"=={specifier}" @@ -327,14 +328,12 @@ class Entry: def strip_version(specifier): from pipenv.patched.pip._vendor.packaging.specifiers import Specifier - op = next( - iter(k for k in Specifier._operators.keys() if specifier.startswith(k)), None - ) + op = next(iter(k for k in Specifier._operators if specifier.startswith(k)), None) if op: specifier = specifier[len(op) :] while op: op = next( - iter(k for k in Specifier._operators.keys() if specifier.startswith(k)), + iter(k for k in Specifier._operators if specifier.startswith(k)), None, ) if op: @@ -656,6 +655,9 @@ def main(argv=None): os.environ["PYTHONIOENCODING"] = "utf-8" os.environ["PYTHONUNBUFFERED"] = "1" parsed = handle_parsed_args(parsed) + if not parsed.verbose: + print(parsed.verbose) + logging.getLogger("pipenv").setLevel(logging.WARN) _main( parsed.pre, parsed.clear, diff --git a/pipenv/routines/graph.py b/pipenv/routines/graph.py index 0a437303..63f63900 100644 --- a/pipenv/routines/graph.py +++ b/pipenv/routines/graph.py @@ -30,7 +30,7 @@ def do_graph(project, bare=False, json=False, json_tree=False, reverse=False): except RuntimeError: pass else: - if not os.name == "nt": # bugfix #4388 + if os.name != "nt": # bugfix #4388 python_path = Path(python_path).as_posix() pipdeptree_path = Path(pipdeptree_path).as_posix() diff --git a/pipenv/routines/install.py b/pipenv/routines/install.py index 4be447dd..1bb0692f 100644 --- a/pipenv/routines/install.py +++ b/pipenv/routines/install.py @@ -604,13 +604,12 @@ def do_init( if categories is None: categories = [] - if not system and not project.s.PIPENV_USE_SYSTEM: - if not project.virtualenv_exists: - try: - do_create_virtualenv(project, python=python, pypi_mirror=pypi_mirror) - except KeyboardInterrupt: - cleanup_virtualenv(project, bare=False) - sys.exit(1) + if not system and not project.s.PIPENV_USE_SYSTEM and not project.virtualenv_exists: + try: + do_create_virtualenv(project, python=python, pypi_mirror=pypi_mirror) + except KeyboardInterrupt: + cleanup_virtualenv(project, bare=False) + sys.exit(1) # Ensure the Pipfile exists. if not deploy: ensure_pipfile(project, system=system) diff --git a/pipenv/routines/lock.py b/pipenv/routines/lock.py index 32a86950..0a79cfc5 100644 --- a/pipenv/routines/lock.py +++ b/pipenv/routines/lock.py @@ -1,3 +1,5 @@ +import contextlib + from pipenv.utils.dependencies import ( get_pipfile_category_using_lockfile_section, ) @@ -54,10 +56,8 @@ def do_lock( ) # Prune old lockfile category as new one will be created. - try: + with contextlib.suppress(KeyError): old_lock_data = lockfile.pop(category) - except KeyError: - pass from pipenv.utils.resolver import venv_resolve_deps diff --git a/pipenv/utils/dependencies.py b/pipenv/utils/dependencies.py index 36050f56..8865dbc7 100644 --- a/pipenv/utils/dependencies.py +++ b/pipenv/utils/dependencies.py @@ -645,10 +645,29 @@ def determine_path_specifier(package: InstallRequirement): if package.link.scheme in ["http", "https"]: return package.link.url_without_fragment if package.link.scheme == "file": + abs_path = Path(package.link.file_path).resolve() + current_dir = Path.cwd() + try: - return Path(package.link.file_path).relative_to(Path.cwd()).as_posix() + relative_path = abs_path.relative_to(current_dir) + return relative_path.as_posix() except ValueError: - return Path(package.link.file_path).as_posix() + # If the direct relative_to fails, manually compute the relative path + common_parts = 0 + for part_a, part_b in zip(abs_path.parts, current_dir.parts): + if part_a == part_b: + common_parts += 1 + else: + break + + # Number of ".." needed are the extra parts in the current directory + # beyond the common parts + up_levels = [".."] * (len(current_dir.parts) - common_parts) + # The relative path is constructed by going up as needed and then + # appending the non-common parts of the absolute path + rel_parts = up_levels + list(abs_path.parts[common_parts:]) + relative_path = Path(*rel_parts) + return relative_path.as_posix() def determine_vcs_specifier(package: InstallRequirement): diff --git a/pipenv/utils/environment.py b/pipenv/utils/environment.py index 2e066eef..89bba8ea 100644 --- a/pipenv/utils/environment.py +++ b/pipenv/utils/environment.py @@ -41,15 +41,14 @@ def load_dot_env(project, as_dict=False, quiet=False): def ensure_environment(): # Skip this on Windows... - if os.name != "nt": - if "LANG" not in os.environ: - click.echo( - "{}: the environment variable {} is not set!" - "\nWe recommend setting this in {} (or equivalent) for " - "proper expected behavior.".format( - click.style("Warning", fg="red", bold=True), - click.style("LANG", bold=True), - click.style("~/.profile", fg="green"), - ), - err=True, - ) + if os.name != "nt" and "LANG" not in os.environ: + click.echo( + "{}: the environment variable {} is not set!" + "\nWe recommend setting this in {} (or equivalent) for " + "proper expected behavior.".format( + click.style("Warning", fg="red", bold=True), + click.style("LANG", bold=True), + click.style("~/.profile", fg="green"), + ), + err=True, + ) diff --git a/pipenv/utils/fileutils.py b/pipenv/utils/fileutils.py index b0c69762..f6fe5d2c 100644 --- a/pipenv/utils/fileutils.py +++ b/pipenv/utils/fileutils.py @@ -212,12 +212,9 @@ def create_tracked_tempdir(*args: Any, **kwargs: Any) -> str: def check_for_unc_path(path): # type: (Path) -> bool """Checks to see if a pathlib `Path` object is a unc path or not.""" - if ( + return bool( os.name == "nt" and len(path.drive) > 2 and not path.drive[0].isalpha() and path.drive[1] != ":" - ): - return True - else: - return False + ) diff --git a/pipenv/utils/funktools.py b/pipenv/utils/funktools.py index 9a056d66..5f33b1e2 100644 --- a/pipenv/utils/funktools.py +++ b/pipenv/utils/funktools.py @@ -348,13 +348,12 @@ def handle_remove_readonly(func, path, exc): try: func(path) except (OSError, FileNotFoundError, PermissionError) as e: # noqa:B014 - if e.errno in PERM_ERRORS: - if e.errno != errno.ENOENT: # File still exists - warnings.warn( - default_warning_message.format(path), - ResourceWarning, - stacklevel=2, - ) + if e.errno in PERM_ERRORS and e.errno != errno.ENOENT: # File still exists + warnings.warn( + default_warning_message.format(path), + ResourceWarning, + stacklevel=2, + ) return else: raise exc_exception diff --git a/pipenv/utils/locking.py b/pipenv/utils/locking.py index c0af54c0..c9552a57 100644 --- a/pipenv/utils/locking.py +++ b/pipenv/utils/locking.py @@ -2,7 +2,7 @@ import copy import itertools import os import stat -from contextlib import contextmanager +from contextlib import contextmanager, suppress from json import JSONDecodeError from pathlib import Path from tempfile import NamedTemporaryFile @@ -61,10 +61,7 @@ def format_requirement_for_lockfile( if req.link and req.link.is_vcs: vcs = req.link.scheme.split("+", 1)[0] entry["ref"] = determine_vcs_revision_hash(req, vcs, pipfile_entry.get("ref")) - if name in original_deps: - entry[vcs] = original_deps[name] - else: - entry[vcs] = req.link.url + entry[vcs] = original_deps.get(name, req.link.url) if pipfile_entry.get("subdirectory"): entry["subdirectory"] = pipfile_entry["subdirectory"] if req.req: @@ -218,18 +215,16 @@ def atomic_open_for_write(target, binary=False, newline=None, encoding=None) -> delete=False, ) # set permissions to 0644 - try: + with suppress(OSError): os.chmod(f.name, stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) - except OSError: - pass + try: yield f except BaseException: f.close() - try: + with suppress(OSError): os.remove(f.name) - except OSError: - pass + raise else: f.close() diff --git a/pipenv/utils/markers.py b/pipenv/utils/markers.py index d1e177b9..21c1c8a5 100644 --- a/pipenv/utils/markers.py +++ b/pipenv/utils/markers.py @@ -48,12 +48,14 @@ class PipenvMarkers(BaseModel): @classmethod def from_pipfile(cls, name, pipfile): attr_fields = list(cls.__fields__) - found_keys = [k for k in pipfile.keys() if k in attr_fields] + found_keys = [k for k in pipfile if k in attr_fields] marker_strings = [f"{k} {pipfile[k]}" for k in found_keys] if pipfile.get("markers"): marker_strings.append(pipfile.get("markers")) if pipfile.get("sys_platform"): marker_strings.append(f"sys_platform '{pipfile['sys_platform']}'") + if pipfile.get("platform_machine"): + marker_strings.append(f"platform_machine '{pipfile['platform_machine']}'") markers = set() for marker in marker_strings: markers.add(marker) @@ -399,9 +401,8 @@ def _markers_contains_key(markers, key): for element in reversed(markers): if isinstance(element, tuple) and element[0].value == key: return True - elif isinstance(element, list): - if _markers_contains_key(element, key): - return True + elif isinstance(element, list) and _markers_contains_key(element, key): + return True return False @@ -628,7 +629,7 @@ def normalize_marker_str(marker) -> str: def marker_from_specifier(spec) -> Marker: - if not any(spec.startswith(k) for k in Specifier._operators.keys()): + if not any(spec.startswith(k) for k in Specifier._operators): if spec.strip().lower() in ["any", "", "*"]: return None spec = f"=={spec}" diff --git a/pipenv/utils/pip.py b/pipenv/utils/pip.py index feb02ee7..040d0170 100644 --- a/pipenv/utils/pip.py +++ b/pipenv/utils/pip.py @@ -136,7 +136,7 @@ def get_pip_args( "src_dir": src_dir, } arg_set = ["--no-input"] if project.settings.get("disable_pip_input", True) else [] - for key in arg_map.keys(): + for key in arg_map: if key in locals() and locals().get(key): arg_set.extend(arg_map.get(key)) arg_set += extra_pip_args or [] diff --git a/pipenv/utils/pipfile.py b/pipenv/utils/pipfile.py index e9b0786e..5ead79c7 100644 --- a/pipenv/utils/pipfile.py +++ b/pipenv/utils/pipfile.py @@ -1,3 +1,4 @@ +import contextlib import io import itertools import os @@ -55,11 +56,10 @@ def find_pipfile(max_depth=3): for c, _, _ in walk_up(os.getcwd()): i += 1 - if i < max_depth: - if "Pipfile": - p = os.path.join(c, "Pipfile") - if os.path.isfile(p): - return p + if i < max_depth and "Pipfile": + p = os.path.join(c, "Pipfile") + if os.path.isfile(p): + return p raise RuntimeError("No Pipfile found!") @@ -190,10 +190,8 @@ class PipfileLoader(pipfiles.Pipfile): for key, klass in pipfiles.PIPFILE_SECTIONS.items(): if key not in data or key == "sources": continue - try: + with contextlib.suppress(Exception): klass.validate(data[key]) - except Exception: - pass @classmethod def ensure_package_sections(cls, data): @@ -207,9 +205,7 @@ class PipfileLoader(pipfiles.Pipfile): sections are present :rtype: :class:`~tomlkit.toml_document.TOMLDocument` """ - package_keys = ( - k for k in pipfiles.PIPFILE_SECTIONS.keys() if k.endswith("packages") - ) + package_keys = (k for k in pipfiles.PIPFILE_SECTIONS if k.endswith("packages")) for key in package_keys: if key not in data: data.update({key: tomlkit.table()}) @@ -401,9 +397,8 @@ class Pipfile(BaseModel): project_path = pipfile_path.parent if not project_path.exists(): raise FileNotFoundError("%s is not a valid project path!" % path) - elif not pipfile_path.exists() or not pipfile_path.is_file(): - if not create: - raise RequirementError("%s is not a valid Pipfile" % pipfile_path) + elif (not pipfile_path.exists() or not pipfile_path.is_file()) and not create: + raise RequirementError("%s is not a valid Pipfile" % pipfile_path) return cls.read_projectfile(pipfile_path.as_posix()) @classmethod diff --git a/pipenv/utils/requirementslib.py b/pipenv/utils/requirementslib.py index 5bb46e78..ef78f4b5 100644 --- a/pipenv/utils/requirementslib.py +++ b/pipenv/utils/requirementslib.py @@ -63,15 +63,14 @@ VCS_SCHEMES = [ def strip_ssh_from_git_uri(uri): # type: (S) -> S """Return git+ssh:// formatted URI to git+git@ format.""" - if isinstance(uri, str): - if "git+ssh://" in uri: - parsed = urlparse(uri) - # split the path on the first separating / so we can put the first segment - # into the 'netloc' section with a : separator - path_part, _, path = parsed.path.lstrip("/").partition("/") - path = f"/{path}" - parsed = parsed._replace(netloc=f"{parsed.netloc}:{path_part}", path=path) - uri = urlunparse(parsed).replace("git+ssh://", "git+", 1) + if isinstance(uri, str) and "git+ssh://" in uri: + parsed = urlparse(uri) + # split the path on the first separating / so we can put the first segment + # into the 'netloc' section with a : separator + path_part, _, path = parsed.path.lstrip("/").partition("/") + path = f"/{path}" + parsed = parsed._replace(netloc=f"{parsed.netloc}:{path_part}", path=path) + uri = urlunparse(parsed).replace("git+ssh://", "git+", 1) return uri @@ -94,7 +93,7 @@ def is_vcs(pipfile_entry): # type: (PipfileType) -> bool """Determine if dictionary entry from Pipfile is for a vcs dependency.""" if isinstance(pipfile_entry, Mapping): - return any(key for key in pipfile_entry.keys() if key in VCS_LIST) + return any(key for key in pipfile_entry if key in VCS_LIST) elif isinstance(pipfile_entry, str): if not is_valid_url(pipfile_entry) and pipfile_entry.startswith("git+"): @@ -136,9 +135,7 @@ def convert_entry_to_path(path): elif "path" in path: path = path["path"] - if not os.name == "nt": - return os.fsdecode(path) - return Path(os.fsdecode(path)).as_posix() + return Path(os.fsdecode(path)).as_posix() if os.name == "nt" else os.fsdecode(path) def is_installable_file(path): diff --git a/pipenv/utils/resolver.py b/pipenv/utils/resolver.py index 8b69d9e8..bee39003 100644 --- a/pipenv/utils/resolver.py +++ b/pipenv/utils/resolver.py @@ -338,6 +338,7 @@ class Resolver: finder = self.package_finder index_lookup = self.prepare_index_lookup() finder._link_collector.index_lookup = index_lookup + finder._link_collector.search_scope.index_restricted = True finder._link_collector.search_scope.index_lookup = index_lookup finder._ignore_compatibility = ignore_compatibility return finder @@ -446,9 +447,49 @@ class Resolver: self.resolved_tree.update(self.results) return self.resolved_tree + def _get_pipfile_markers(self, pipfile_entry): + sys_platform = pipfile_entry.get("sys_platform") + platform_machine = pipfile_entry.get("platform_machine") + markers = pipfile_entry.get("markers") + + if sys_platform: + sys_platform = f"sys_platform {sys_platform}" + if platform_machine: + platform_machine = f"platform_machine {platform_machine}" + + combined_markers = [ + f"({marker})" + for marker in (sys_platform, markers, platform_machine) + if marker + ] + + return " and ".join(combined_markers).strip() + + def _fold_markers(self, dependency_tree, install_req): + comes_from = dependency_tree[install_req.name] + + if comes_from == "Pipfile": + pipfile_entry = self.pipfile_entries.get(install_req.name) + if pipfile_entry and isinstance(pipfile_entry, dict): + return self._get_pipfile_markers(pipfile_entry) + else: + markers = self._fold_markers(dependency_tree, comes_from) + if markers: + self.markers_lookup[install_req.name] = markers + return markers + def resolve_constraints(self): from .markers import marker_from_specifier + # Build mapping of where package originates from + comes_from = {} + for result in self.resolved_tree: + if isinstance(result.comes_from, InstallRequirement): + comes_from[result.name] = result.comes_from + else: + comes_from[result.name] = "Pipfile" + + # Build up the results tree with markers new_tree = set() for result in self.resolved_tree: if result.markers: @@ -476,6 +517,11 @@ class Resolver: err=True, ) new_tree.add(result) + + # Fold markers + for result in new_tree: + self._fold_markers(comes_from, result) + self.resolved_tree = new_tree def collect_hashes(self, ireq): @@ -551,7 +597,7 @@ class Resolver: reqs = [(ireq,) for ireq in self.resolved_tree] results = {} for (ireq,) in reqs: - if normalize_name(ireq.name) in self.skipped.keys(): + if normalize_name(ireq.name) in self.skipped: continue collected_hashes = self.hashes.get(ireq, set()) if collected_hashes: diff --git a/pipenv/utils/shell.py b/pipenv/utils/shell.py index 77236525..dd7795ab 100644 --- a/pipenv/utils/shell.py +++ b/pipenv/utils/shell.py @@ -199,16 +199,12 @@ def get_workon_home(): def is_file(package): """Determine if a package name is for a File dependency.""" if hasattr(package, "keys"): - return any(key for key in package.keys() if key in ["file", "path"]) + return any(key for key in package if key in ["file", "path"]) if os.path.exists(str(package)): return True - for start in SCHEME_LIST: - if str(package).startswith(start): - return True - - return False + return any(str(package).startswith(start) for start in SCHEME_LIST) def is_virtual_environment(path): diff --git a/pipenv/utils/toml.py b/pipenv/utils/toml.py index 7fbdfcf1..1eec3fed 100644 --- a/pipenv/utils/toml.py +++ b/pipenv/utils/toml.py @@ -23,10 +23,9 @@ def cleanup_toml(tml): # Add newlines between TOML sections. for i, line in enumerate(toml.split("\n")): # Skip the first line. - if line.startswith("["): - if i > 0: - # Insert a newline before the heading. - new_toml.append("") + if line.startswith("[") and i > 0: + # Insert a newline before the heading. + new_toml.append("") new_toml.append(line) # adding new line at the end of the TOML file new_toml.append("") diff --git a/pipenv/utils/virtualenv.py b/pipenv/utils/virtualenv.py index dd1bf128..562d4ccc 100644 --- a/pipenv/utils/virtualenv.py +++ b/pipenv/utils/virtualenv.py @@ -1,3 +1,4 @@ +import contextlib import os import shutil import sys @@ -179,12 +180,11 @@ def ensure_virtualenv(project, python=None, site_packages=None, pypi_mirror=None # If VIRTUAL_ENV is set, there is a possibility that we are # going to remove the active virtualenv that the user cares # about, so confirm first. - if "VIRTUAL_ENV" in os.environ: - if not ( - project.s.PIPENV_YES - or click.confirm("Use existing virtualenv?", default=True) - ): - abort() + if "VIRTUAL_ENV" in os.environ and not ( + project.s.PIPENV_YES + or click.confirm("Use existing virtualenv?", default=True) + ): + abort() click.echo(click.style("Using existing virtualenv...", bold=True), err=True) # Remove the virtualenv. cleanup_virtualenv(project, bare=True) @@ -261,15 +261,12 @@ def ensure_python(project, python=None): # method of the user for new python installs. installer = None if not project.s.PIPENV_DONT_USE_PYENV: - try: + with contextlib.suppress(InstallerNotFound): installer = Pyenv(project) - except InstallerNotFound: - pass + if installer is None and not project.s.PIPENV_DONT_USE_ASDF: - try: + with contextlib.suppress(InstallerNotFound): installer = Asdf(project) - except InstallerNotFound: - pass if not installer: abort("Neither 'pyenv' nor 'asdf' could be found to install Python.") diff --git a/tasks/vendoring/__init__.py b/tasks/vendoring/__init__.py index 6157b58e..a469ee8b 100644 --- a/tasks/vendoring/__init__.py +++ b/tasks/vendoring/__init__.py @@ -395,9 +395,10 @@ def vendor(ctx, vendor_dir, package=None, rewrite=True): log("Rewriting imports for %s..." % item) rewrite_imports(item, vendored_libs) rename_if_needed(ctx, vendor_dir, item) - elif item.name not in FILE_WHITE_LIST: - if rewrite and not package or (package and item.stem.lower() in package): - rewrite_file_imports(item, vendored_libs) + elif item.name not in FILE_WHITE_LIST and ( + rewrite and not package or (package and item.stem.lower() in package) + ): + rewrite_file_imports(item, vendored_libs) if not package: apply_patches(ctx, patched=is_patched, pre=False) if is_patched: @@ -793,9 +794,8 @@ def vendor_artifact(ctx, package, version=None): dest_dir.mkdir() _, _, dest_path = urllib3_parse(link).path.rpartition("/") dest_file = dest_dir / dest_path - with open(dest_file.as_posix(), "wb") as target_handle: - with open_file(link) as fp: - if fp is None: - print(f"Error downloading {link}") - continue - shutil.copyfileobj(fp, target_handle) + with open(dest_file.as_posix(), "wb") as target_handle, open_file(link) as fp: + if fp is None: + print(f"Error downloading {link}") + continue + shutil.copyfileobj(fp, target_handle) diff --git a/tasks/vendoring/patches/patched/pip_index_safety.patch b/tasks/vendoring/patches/patched/pip_index_safety.patch index e8acac5e..cf5d6020 100644 --- a/tasks/vendoring/patches/patched/pip_index_safety.patch +++ b/tasks/vendoring/patches/patched/pip_index_safety.patch @@ -1,5 +1,5 @@ diff --git a/pipenv/patched/pip/_internal/index/collector.py b/pipenv/patched/pip/_internal/index/collector.py -index 0120610c..ead5227e 100644 +index b3e293ea3..f27a88725 100644 --- a/pipenv/patched/pip/_internal/index/collector.py +++ b/pipenv/patched/pip/_internal/index/collector.py @@ -412,9 +412,11 @@ class LinkCollector: @@ -36,7 +36,7 @@ index 0120610c..ead5227e 100644 return link_collector diff --git a/pipenv/patched/pip/_internal/models/search_scope.py b/pipenv/patched/pip/_internal/models/search_scope.py -index fe61e8116..dab85fbb9 100644 +index fe61e8116..98a2cc97f 100644 --- a/pipenv/patched/pip/_internal/models/search_scope.py +++ b/pipenv/patched/pip/_internal/models/search_scope.py @@ -3,7 +3,7 @@ import logging @@ -53,40 +53,44 @@ index fe61e8116..dab85fbb9 100644 """ - __slots__ = ["find_links", "index_urls", "no_index"] -+ __slots__ = ["find_links", "index_urls", "no_index", "index_lookup"] ++ __slots__ = ["find_links", "index_urls", "no_index", "index_lookup", "index_restricted"] @classmethod def create( -@@ -28,6 +28,7 @@ class SearchScope: +@@ -28,6 +28,8 @@ class SearchScope: find_links: List[str], index_urls: List[str], no_index: bool, + index_lookup: Optional[Dict[str, List[str]]] = None, ++ index_restricted: bool = False, ) -> "SearchScope": """ Create a SearchScope object after normalizing the `find_links`. -@@ -62,6 +63,7 @@ class SearchScope: +@@ -62,6 +64,8 @@ class SearchScope: find_links=built_find_links, index_urls=index_urls, no_index=no_index, + index_lookup=index_lookup, ++ index_restricted=index_restricted, ) def __init__( -@@ -69,10 +71,12 @@ class SearchScope: +@@ -69,10 +73,14 @@ class SearchScope: find_links: List[str], index_urls: List[str], no_index: bool, + index_lookup: Optional[Dict[str, List[str]]] = None, ++ index_restricted: bool = False, ) -> None: self.find_links = find_links self.index_urls = index_urls self.no_index = no_index + self.index_lookup = index_lookup if index_lookup else {} ++ self.index_restricted = index_restricted def get_formatted_locations(self) -> str: lines = [] -@@ -129,4 +133,9 @@ class SearchScope: +@@ -129,4 +137,9 @@ class SearchScope: loc = loc + "/" return loc @@ -94,6 +98,6 @@ index fe61e8116..dab85fbb9 100644 + index_urls = self.index_urls + if project_name in self.index_lookup: + index_urls = [self.index_lookup[project_name]] -+ elif self.index_urls: ++ elif self.index_restricted and self.index_urls: + index_urls = [self.index_urls[0]] + return [mkurl_pypi_url(url) for url in index_urls] diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 1c8c0695..e16f7835 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -18,6 +18,7 @@ from pipenv.vendor import tomlkit from pipenv.utils.processes import subprocess_run from pipenv.utils.funktools import handle_remove_readonly from pipenv.utils.shell import temp_environ +import contextlib log = logging.getLogger(__name__) warnings.simplefilter("default", category=ResourceWarning) @@ -61,7 +62,7 @@ def check_github_ssh(): # registered with GitHub. Otherwise, the command will fail with # return_code=255 and say 'Permission denied (publickey).' c = subprocess_run('ssh -o StrictHostKeyChecking=no -o CheckHostIP=no -T git@github.com', timeout=30, shell=True) - res = True if c.returncode == 1 else False + res = c.returncode == 1 except KeyboardInterrupt: warnings.warn( "KeyboardInterrupt while checking GitHub ssh access", RuntimeWarning, stacklevel=1 @@ -145,9 +146,8 @@ class _Pipfile: def remove(self, package, dev=False): section = "packages" if not dev else "dev-packages" - if not dev and package not in self.document[section]: - if package in self.document["dev-packages"]: - section = "dev-packages" + if not dev and package not in self.document[section] and package in self.document["dev-packages"]: + section = "dev-packages" del self.document[section][package] self.write() @@ -164,7 +164,7 @@ class _Pipfile: if not self.document.get("source"): source_table = tomlkit.table() source_table["url"] = self.index - source_table["verify_ssl"] = True if self.index.startswith("https") else False + source_table["verify_ssl"] = bool(self.index.startswith("https")) source_table["name"] = "pipenv_test_index" self.document["source"].append(source_table) return tomlkit.dumps(self.document) @@ -204,10 +204,9 @@ class _PipenvInstance: self.pipfile_path = p_path if pipfile: - try: + with contextlib.suppress(FileNotFoundError): os.remove(p_path) - except FileNotFoundError: - pass + with open(p_path, 'a'): os.utime(p_path, None) @@ -221,10 +220,9 @@ class _PipenvInstance: def __exit__(self, *args): warn_msg = 'Failed to remove resource: {!r}' if self.pipfile_path: - try: + with contextlib.suppress(OSError): os.remove(self.pipfile_path) - except OSError: - pass + os.chdir(self.original_dir) if self._path: try: diff --git a/tests/integration/test_dot_venv.py b/tests/integration/test_dot_venv.py index 98074dcb..ce920e63 100644 --- a/tests/integration/test_dot_venv.py +++ b/tests/integration/test_dot_venv.py @@ -50,17 +50,16 @@ def test_venv_in_project_disabled_ignores_venv(false_value, pipenv_instance_pypi @pytest.mark.dotvenv @pytest.mark.parametrize("true_value", TRUE_VALUES) def test_venv_at_project_root(true_value, pipenv_instance_pypi): - with temp_environ(): - with pipenv_instance_pypi() as p: - os.environ['PIPENV_VENV_IN_PROJECT'] = true_value - c = p.pipenv('install') - assert c.returncode == 0 - assert normalize_drive(p.path) in p.pipenv('--venv').stdout - del os.environ['PIPENV_VENV_IN_PROJECT'] - os.mkdir('subdir') - os.chdir('subdir') - # should still detect installed - assert normalize_drive(p.path) in p.pipenv('--venv').stdout + with temp_environ(), pipenv_instance_pypi() as p: + os.environ['PIPENV_VENV_IN_PROJECT'] = true_value + c = p.pipenv('install') + assert c.returncode == 0 + assert normalize_drive(p.path) in p.pipenv('--venv').stdout + del os.environ['PIPENV_VENV_IN_PROJECT'] + os.mkdir('subdir') + os.chdir('subdir') + # should still detect installed + assert normalize_drive(p.path) in p.pipenv('--venv').stdout @pytest.mark.dotvenv @@ -136,22 +135,21 @@ def test_empty_venv_file(pipenv_instance_pypi): def test_venv_in_project_default_when_venv_exists(pipenv_instance_pypi): """Tests virtualenv creation when a .venv file exists at the project root. """ - with temp_environ(), pipenv_instance_pypi() as p: - with TemporaryDirectory( - prefix='pipenv-', suffix='-test_venv' - ) as venv_path: - file_path = os.path.join(p.path, '.venv') - with open(file_path, 'w') as f: - f.write(venv_path) + with temp_environ(), pipenv_instance_pypi() as p, TemporaryDirectory( + prefix='pipenv-', suffix='-test_venv' + ) as venv_path: + file_path = os.path.join(p.path, '.venv') + with open(file_path, 'w') as f: + f.write(venv_path) - c = p.pipenv('install') - assert c.returncode == 0 - c = p.pipenv('--venv') - assert c.returncode == 0 - venv_loc = Path(c.stdout.strip()) + c = p.pipenv('install') + assert c.returncode == 0 + c = p.pipenv('--venv') + assert c.returncode == 0 + venv_loc = Path(c.stdout.strip()) - assert venv_loc.joinpath('.project').exists() - assert venv_loc == Path(venv_path) + assert venv_loc.joinpath('.project').exists() + assert venv_loc == Path(venv_path) @pytest.mark.dotenv diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index 3f3f1d3d..02d5b855 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -31,8 +31,8 @@ def test_mirror_install(pipenv_instance_pypi): # Ensure the --pypi-mirror parameter hasn't altered the Pipfile or Pipfile.lock sources assert len(p.pipfile["source"]) == 1 assert len(p.lockfile["_meta"]["sources"]) == 1 - assert "https://pypi.org/simple" == p.pipfile["source"][0]["url"] - assert "https://pypi.org/simple" == p.lockfile["_meta"]["sources"][0]["url"] + assert p.pipfile["source"][0]["url"] == "https://pypi.org/simple" + assert p.lockfile["_meta"]["sources"][0]["url"] == "https://pypi.org/simple" assert "dataclasses-json" in p.pipfile["packages"] assert "dataclasses-json" in p.lockfile["default"] @@ -345,21 +345,20 @@ def test_editable_no_args(pipenv_instance_pypi): def test_install_venv_project_directory(pipenv_instance_pypi): """Test the project functionality during virtualenv creation. """ - with pipenv_instance_pypi() as p: - with temp_environ(), TemporaryDirectory( - prefix="pipenv-", suffix="temp_workon_home" - ) as workon_home: - os.environ["WORKON_HOME"] = workon_home + with pipenv_instance_pypi() as p, temp_environ(), TemporaryDirectory( + prefix="pipenv-", suffix="temp_workon_home" + ) as workon_home: + os.environ["WORKON_HOME"] = workon_home - c = p.pipenv("install six") - assert c.returncode == 0 + c = p.pipenv("install six") + assert c.returncode == 0 - venv_loc = None - for line in c.stderr.splitlines(): - if line.startswith("Virtualenv location:"): - venv_loc = Path(line.split(":", 1)[-1].strip()) - assert venv_loc is not None - assert venv_loc.joinpath(".project").exists() + venv_loc = None + for line in c.stderr.splitlines(): + if line.startswith("Virtualenv location:"): + venv_loc = Path(line.split(":", 1)[-1].strip()) + assert venv_loc is not None + assert venv_loc.joinpath(".project").exists() @pytest.mark.cli diff --git a/tests/integration/test_install_markers.py b/tests/integration/test_install_markers.py index f72a98d3..98c3ed9a 100644 --- a/tests/integration/test_install_markers.py +++ b/tests/integration/test_install_markers.py @@ -157,10 +157,9 @@ def test_resolver_unique_markers(pipenv_instance_pypi): @pytest.mark.project @pytest.mark.needs_internet def test_environment_variable_value_does_not_change_hash(pipenv_instance_private_pypi): - with pipenv_instance_private_pypi() as p: - with temp_environ(): - with open(p.pipfile_path, 'w') as f: - f.write(""" + with pipenv_instance_private_pypi() as p, temp_environ(): + with open(p.pipfile_path, 'w') as f: + f.write(""" [[source]] url = 'https://${PYPI_USERNAME}:${PYPI_PASSWORD}@pypi.org/simple' verify_ssl = true @@ -169,24 +168,24 @@ name = 'pypi' [packages] six = "*" """) - project = Project() + project = Project() - os.environ['PYPI_USERNAME'] = 'whatever' - os.environ['PYPI_PASSWORD'] = 'pass' - assert project.get_lockfile_hash() is None + os.environ['PYPI_USERNAME'] = 'whatever' + os.environ['PYPI_PASSWORD'] = 'pass' + assert project.get_lockfile_hash() is None - c = p.pipenv('install') - assert c.returncode == 0 - lock_hash = project.get_lockfile_hash() - assert lock_hash is not None - assert lock_hash == project.calculate_pipfile_hash() + c = p.pipenv('install') + assert c.returncode == 0 + lock_hash = project.get_lockfile_hash() + assert lock_hash is not None + assert lock_hash == project.calculate_pipfile_hash() - assert c.returncode == 0 - assert project.get_lockfile_hash() == project.calculate_pipfile_hash() + assert c.returncode == 0 + assert project.get_lockfile_hash() == project.calculate_pipfile_hash() - os.environ['PYPI_PASSWORD'] = 'pass2' - assert project.get_lockfile_hash() == project.calculate_pipfile_hash() + os.environ['PYPI_PASSWORD'] = 'pass2' + assert project.get_lockfile_hash() == project.calculate_pipfile_hash() - with open(p.pipfile_path, 'a') as f: - f.write('requests = "==2.14.0"\n') - assert project.get_lockfile_hash() != project.calculate_pipfile_hash() + with open(p.pipfile_path, 'a') as f: + f.write('requests = "==2.14.0"\n') + assert project.get_lockfile_hash() != project.calculate_pipfile_hash() diff --git a/tests/integration/test_install_uri.py b/tests/integration/test_install_uri.py index 01855f5e..b07f52a5 100644 --- a/tests/integration/test_install_uri.py +++ b/tests/integration/test_install_uri.py @@ -139,8 +139,8 @@ six = "*" @pytest.mark.install @pytest.mark.needs_internet @pytest.mark.skipif(sys.version_info >= (3, 12), reason="Package does not work with Python 3.12") -def test_install_specifying_index_url(pipenv_instance_pypi): - with pipenv_instance_pypi() as p: +def test_install_specifying_index_url(pipenv_instance_private_pypi): + with pipenv_instance_private_pypi() as p: with open(p.pipfile_path, "w") as f: contents = """ [[source]] @@ -153,6 +153,8 @@ six = "*" [dev-packages] +[pipenv] +install_search_all_sources = true """.strip() f.write(contents) c = p.pipenv("install pipenv-test-private-package --index https://test.pypi.org/simple") diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py index 7bc9ea68..0259f6ba 100644 --- a/tests/integration/test_lock.py +++ b/tests/integration/test_lock.py @@ -220,19 +220,18 @@ allow_prereleases = true @flaky def test_complex_deps_lock_and_install_properly(pipenv_instance_pypi): # This uses the real PyPI because Maya has too many dependencies... - with pipenv_instance_pypi() as p: - with open(p.pipfile_path, 'w') as f: - contents = """ + with pipenv_instance_pypi() as p, open(p.pipfile_path, 'w') as f: + contents = """ [packages] maya = "*" """.strip() - f.write(contents) + f.write(contents) - c = p.pipenv('lock --verbose') - assert c.returncode == 0 + c = p.pipenv('lock --verbose') + assert c.returncode == 0 - c = p.pipenv('install') - assert c.returncode == 0 + c = p.pipenv('install') + assert c.returncode == 0 @pytest.mark.lock @@ -647,3 +646,31 @@ dataclasses-json = {extras = ["dev"], version = "==0.5.7"} assert "dataclasses-json" in p.pipfile["packages"] assert "dataclasses-json" in p.lockfile["default"] assert p.lockfile["default"]["dataclasses-json"].get("markers", "") is not None + +@pytest.mark.index +@pytest.mark.install # private indexes need to be uncached for resolution +@pytest.mark.skip_lock +@pytest.mark.needs_internet +def test_private_index_skip_lock(pipenv_instance_private_pypi): + with pipenv_instance_private_pypi() as p: + with open(p.pipfile_path, 'w') as f: + contents = """ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[[source]] +url = "https://test.pypi.org/simple" +verify_ssl = true +name = "testpypi" + +[packages] +pipenv-test-private-package = {version = "*", index = "testpypi"} + +[pipenv] +install_search_all_sources = true + """.strip() + f.write(contents) + c = p.pipenv('install --skip-lock') + assert c.returncode == 0 diff --git a/tests/integration/test_pipenv.py b/tests/integration/test_pipenv.py index 614af3a8..3fb69abd 100644 --- a/tests/integration/test_pipenv.py +++ b/tests/integration/test_pipenv.py @@ -74,11 +74,10 @@ def test_proper_names_unmanaged_virtualenv(pipenv_instance_pypi): @pytest.mark.cli def test_directory_with_leading_dash(pipenv_instance_pypi): - with temp_environ(): - with pipenv_instance_pypi() as p: - c = p.pipenv('run pip freeze') - assert c.returncode == 0 - c = p.pipenv('--venv') - assert c.returncode == 0 - venv_path = c.stdout.strip() - assert os.path.isdir(venv_path) + with temp_environ(), pipenv_instance_pypi() as p: + c = p.pipenv('run pip freeze') + assert c.returncode == 0 + c = p.pipenv('--venv') + assert c.returncode == 0 + venv_path = c.stdout.strip() + assert os.path.isdir(venv_path) diff --git a/tests/integration/test_project.py b/tests/integration/test_project.py index c4be350d..39f01fca 100644 --- a/tests/integration/test_project.py +++ b/tests/integration/test_project.py @@ -13,10 +13,9 @@ from pipenv.utils.fileutils import normalize_path @pytest.mark.sources @pytest.mark.environ def test_pipfile_envvar_expansion(pipenv_instance_pypi): - with pipenv_instance_pypi() as p: - with temp_environ(): - with open(p.pipfile_path, 'w') as f: - f.write(""" + with pipenv_instance_pypi() as p, temp_environ(): + with open(p.pipfile_path, 'w') as f: + f.write(""" [[source]] url = 'https://${TEST_HOST}/simple' verify_ssl = false @@ -25,11 +24,11 @@ name = "pypi" [packages] pytz = "*" """.strip()) - os.environ['TEST_HOST'] = 'localhost:5000' - project = Project() - assert project.sources[0]['url'] == 'https://localhost:5000/simple' - assert 'localhost:5000' not in str(Pipfile.load(open(p.pipfile_path))) - print(str(Pipfile.load(open(p.pipfile_path)))) + os.environ['TEST_HOST'] = 'localhost:5000' + project = Project() + assert project.sources[0]['url'] == 'https://localhost:5000/simple' + assert 'localhost:5000' not in str(Pipfile.load(open(p.pipfile_path))) + print(str(Pipfile.load(open(p.pipfile_path)))) @pytest.mark.project diff --git a/tests/integration/test_uninstall.py b/tests/integration/test_uninstall.py index 06892bdc..f9738598 100644 --- a/tests/integration/test_uninstall.py +++ b/tests/integration/test_uninstall.py @@ -60,8 +60,8 @@ def test_mirror_uninstall(pipenv_instance_pypi): # Ensure the --pypi-mirror parameter hasn't altered the Pipfile or Pipfile.lock sources assert len(p.pipfile["source"]) == 1 assert len(p.lockfile["_meta"]["sources"]) == 1 - assert "https://pypi.org/simple" == p.pipfile["source"][0]["url"] - assert "https://pypi.org/simple" == p.lockfile["_meta"]["sources"][0]["url"] + assert p.pipfile["source"][0]["url"] == "https://pypi.org/simple" + assert p.lockfile["_meta"]["sources"][0]["url"] == "https://pypi.org/simple" c = p.pipenv("run python -m django --version") assert c.returncode == 0 @@ -74,8 +74,8 @@ def test_mirror_uninstall(pipenv_instance_pypi): # Ensure the --pypi-mirror parameter hasn't altered the Pipfile or Pipfile.lock sources assert len(p.pipfile["source"]) == 1 assert len(p.lockfile["_meta"]["sources"]) == 1 - assert "https://pypi.org/simple" == p.pipfile["source"][0]["url"] - assert "https://pypi.org/simple" == p.lockfile["_meta"]["sources"][0]["url"] + assert p.pipfile["source"][0]["url"] == "https://pypi.org/simple" + assert p.lockfile["_meta"]["sources"][0]["url"] == "https://pypi.org/simple" c = p.pipenv("run python -m django --version") assert c.returncode > 0