Repository: pex-tool/pex

Issue:
Release 2.1.73
On the docket:
+ [x] Unexpected distribution hash #1683 
+ [x] Pex fails to parse wheel tags correctly when resolving from a lock. #1676 
+ [x] `pex3 lock create --style universal` does not fully patch ambient interpreter properties. #1681 


Discussion:
Split off from "Release 2.1.72 #1663" to make way for a fix for fixes related to Pants' `pex3 lock` adoption.

Resolving patch:
diff --git a/pex/pip/runtime_patches.py b/pex/pip/runtime_patches.py
--- a/pex/pip/runtime_patches.py
+++ b/pex/pip/runtime_patches.py
@@ -134,7 +134,11 @@ def supported(self, *_args, **_kwargs):
     #
     # Much like 2 (wheel applicability), we want to gather distributions
     # even when they require different Pythons than the system Python.
+    #
+    # Unlike the other two patches, this patch diverges between the pip-legacy-resolver and the
+    # pip-2020-resolver.
     def patch_requires_python():
+        # The pip-legacy-resolver patch.
         from pip._internal.utils import packaging  # type: ignore[import]
 
         if python_full_versions:
@@ -154,6 +158,44 @@ def check_requires_python(requires_python, *_args, **_kw):
         else:
             packaging.check_requires_python = lambda *_args, **_kw: True
 
+        # The pip-2020-resolver patch.
+        from pip._internal.resolution.resolvelib.candidates import (  # type: ignore[import]
+            RequiresPythonCandidate,
+        )
+        from pip._internal.resolution.resolvelib.requirements import (  # type: ignore[import]
+            RequiresPythonRequirement,
+        )
+
+        if python_full_versions:
+            orig_get_candidate_lookup = RequiresPythonRequirement.get_candidate_lookup
+            orig_is_satisfied_by = RequiresPythonRequirement.is_satisfied_by
+
+            def get_candidate_lookup(self):
+                for python_full_version in python_full_versions:
+                    delegate = RequiresPythonRequirement(
+                        self.specifier, RequiresPythonCandidate(python_full_version)
+                    )
+                    candidate_lookup = orig_get_candidate_lookup(delegate)
+                    if candidate_lookup != (None, None):
+                        return candidate_lookup
+                return None, None
+
+            def is_satisfied_by(self, *_args, **_kw):
+                # Ensure any dependency we lock is compatible with the full interpreter range
+                # specified since we have no way to force Pip to backtrack and follow paths for any
+                # divergences. Most (all?) true divergences should be covered by forked environment
+                # markers.
+                return all(
+                    orig_is_satisfied_by(self, RequiresPythonCandidate(python_full_version))
+                    for python_full_version in python_full_versions
+                )
+
+            RequiresPythonRequirement.get_candidate_lookup = get_candidate_lookup
+            RequiresPythonRequirement.is_satisfied_by = is_satisfied_by
+        else:
+            RequiresPythonRequirement.get_candidate_lookup = lambda self: (self._candidate, None)
+            RequiresPythonRequirement.is_satisfied_by = lambda *_args, **_kw: True
+
     patch_requires_python()
     del patch_requires_python
 else:


Test patch:
diff --git a/tests/integration/cli/commands/test_lock.py b/tests/integration/cli/commands/test_lock.py
--- a/tests/integration/cli/commands/test_lock.py
+++ b/tests/integration/cli/commands/test_lock.py
@@ -718,7 +718,7 @@ def test_excludes_pep517_build_requirements_issue_1565(tmpdir):
     )
 
 
-UNIVERSAL_LOCKFILE_CONTENTS = """\
+LEGACY_UNIVERSAL_LOCKFILE_CONTENTS = """\
 {
   "allow_builds": true,
   "allow_prereleases": false,
@@ -1033,15 +1033,347 @@ def test_excludes_pep517_build_requirements_issue_1565(tmpdir):
 """
 
 
-UNIVERSAL_LOCKFILE = lockfile.loads(UNIVERSAL_LOCKFILE_CONTENTS)
+PIP_2020_UNIVERSAL_LOCKFILE_CONTENTS = """\
+{
+  "allow_builds": true,
+  "allow_prereleases": false,
+  "allow_wheels": true,
+  "build_isolation": true,
+  "constraints": [
+    "cffi==1.15",
+    "cryptography==35.0.0",
+    "ndg-httpsclient==0.5.1",
+    "pyasn1==0.4.8",
+    "pycparser==2.21",
+    "pyopenssl==21",
+    "six==1.16"
+  ],
+  "locked_resolves": [
+    {
+      "locked_requirements": [
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139",
+              "url": "https://files.pythonhosted.org/packages/bd/92/25f744cbe55e7e54b35f256f9fdd50a590c434cf47afb78b8a6278a87c2d/cffi-1.15.0-cp39-cp39-win_amd64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954",
+              "url": "https://files.pythonhosted.org/packages/00/9e/92de7e1217ccc3d5f352ba21e52398372525765b2e0c4530e6eb2ba9282a/cffi-1.15.0.tar.gz"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a",
+              "url": "https://files.pythonhosted.org/packages/03/31/b714d1f35e896fa36c302e024a9ccad3c6952660bcbb1a43188ef20f3ec3/cffi-1.15.0-cp39-cp39-win32.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a",
+              "url": "https://files.pythonhosted.org/packages/39/02/960252ec9b39840e20a279de29a6fda9b4e49be79e0f32f0cfdf3e61cc4f/cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37",
+              "url": "https://files.pythonhosted.org/packages/3e/9b/660d6da900af1976a8b4efea713a7ce9e514bf4659eff9b17f90f00be1cf/cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a",
+              "url": "https://files.pythonhosted.org/packages/61/51/cff222be618f0e060a6991ab387f9574776fd0711a63b2be80df47ec5fad/cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796",
+              "url": "https://files.pythonhosted.org/packages/6a/5e/d33fdd7461fba6e3b0f8fc4141eba410be16af81cf1ed32223a40abe27ac/cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8",
+              "url": "https://files.pythonhosted.org/packages/93/bc/a6b9abd8f692278a8e63759136f47ce69e564a7bcfa7ae7e5561243c74f3/cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df",
+              "url": "https://files.pythonhosted.org/packages/de/a9/ab4725702c9e5b77643136228a983194fa6e39ea387d964b3c827159d780/cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e",
+              "url": "https://files.pythonhosted.org/packages/e2/25/00fd291e0872d43dabe070e7b761ba37453a1a94bd6e28c31b73112d8f0c/cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl"
+            }
+          ],
+          "project_name": "cffi",
+          "requires_dists": [
+            "pycparser"
+          ],
+          "requires_python": null,
+          "version": "1.15"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588",
+              "url": "https://files.pythonhosted.org/packages/93/4b/8f402b9b22cec331d00c6ec2f26184db6e78f53ba24abba8f51b4416bb7b/cryptography-35.0.0-cp36-abi3-win_amd64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992",
+              "url": "https://files.pythonhosted.org/packages/07/fa/f63509370561201ffa852e4f3fb105c76ced6927f951e4cc6a3973d1a527/cryptography-35.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8",
+              "url": "https://files.pythonhosted.org/packages/0d/7b/355c4a20149417ddae61090089c23d42c7e138f33b37bd62f63638f3982f/cryptography-35.0.0-cp36-abi3-win32.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d",
+              "url": "https://files.pythonhosted.org/packages/10/91/90b8d4cd611ac2aa526290ae4b4285aa5ea57ee191c63c2f3d04170d7683/cryptography-35.0.0.tar.gz"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9",
+              "url": "https://files.pythonhosted.org/packages/21/d8/ac396584e4559711240018bef74f7359c1dc769febb49973ff0ec397e7bb/cryptography-35.0.0-cp36-abi3-macosx_10_10_x86_64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6",
+              "url": "https://files.pythonhosted.org/packages/79/92/7238415a8a624dd74fcb0603fcb222df399210b4713adf8d82e16fd1c76a/cryptography-35.0.0-cp36-abi3-macosx_11_0_arm64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6",
+              "url": "https://files.pythonhosted.org/packages/7b/1a/bf49bade5080a5cfb226a975c118fc56c3df2878b91809a5030dd87e551b/cryptography-35.0.0-cp36-abi3-manylinux_2_24_x86_64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d",
+              "url": "https://files.pythonhosted.org/packages/83/7c/eb142fff52eb1dda06eaa32ceceec2f9019711dd00c4a12bd9312930a3cc/cryptography-35.0.0-cp36-abi3-musllinux_1_1_aarch64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e",
+              "url": "https://files.pythonhosted.org/packages/94/bd/0d36bb113967ab8bc75f58d692846fd27ed64b8d5a7436a672b66976f802/cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d",
+              "url": "https://files.pythonhosted.org/packages/c6/dc/4ca9999befed87830c9ecdf9d2e85019b4090f6439754ee9308e1dafba06/cryptography-35.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa",
+              "url": "https://files.pythonhosted.org/packages/d5/7d/0d8895b3b4aac0cab30a5c285f9a7fc381792e66f6c8d0c055b55259e0d7/cryptography-35.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6",
+              "url": "https://files.pythonhosted.org/packages/eb/b2/1812dfe3eefa9256e565c0c81bf2ae40698fc174e8407996d14a63faa126/cryptography-35.0.0-cp36-abi3-musllinux_1_1_x86_64.whl"
+            }
+          ],
+          "project_name": "cryptography",
+          "requires_dists": [
+            "bcrypt>=3.1.5; extra == \\"ssh\\"",
+            "black; extra == \\"pep8test\\"",
+            "cffi>=1.12",
+            "doc8; extra == \\"docstest\\"",
+            "flake8-import-order; extra == \\"pep8test\\"",
+            "flake8; extra == \\"pep8test\\"",
+            "hypothesis!=3.79.2,>=1.11.4; extra == \\"test\\"",
+            "iso8601; extra == \\"test\\"",
+            "pep8-naming; extra == \\"pep8test\\"",
+            "pretend; extra == \\"test\\"",
+            "pyenchant>=1.6.11; extra == \\"docstest\\"",
+            "pytest-cov; extra == \\"test\\"",
+            "pytest-subtests; extra == \\"test\\"",
+            "pytest-xdist; extra == \\"test\\"",
+            "pytest>=6.2.0; extra == \\"test\\"",
+            "pytz; extra == \\"test\\"",
+            "setuptools-rust>=0.11.4; extra == \\"sdist\\"",
+            "sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5; extra == \\"docs\\"",
+            "sphinx-rtd-theme; extra == \\"docs\\"",
+            "sphinxcontrib-spelling>=4.0.1; extra == \\"docstest\\"",
+            "twine>=1.12.0; extra == \\"docstest\\""
+          ],
+          "requires_python": ">=3.6",
+          "version": "35"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "dd174c11d971b6244a891f7be2b32ca9853d3797a72edb34fa5d7b07d8fff7d4",
+              "url": "https://files.pythonhosted.org/packages/fb/67/c2f508c00ed2a6911541494504b7cac16fe0b0473912568df65fd1801132/ndg_httpsclient-0.5.1-py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "d72faed0376ab039736c2ba12e30695e2788c4aa569c9c3e3d72131de2592210",
+              "url": "https://files.pythonhosted.org/packages/b9/f8/8f49278581cb848fb710a362bfc3028262a82044167684fb64ad068dbf92/ndg_httpsclient-0.5.1.tar.gz"
+            }
+          ],
+          "project_name": "ndg-httpsclient",
+          "requires_dists": [
+            "PyOpenSSL",
+            "pyasn1>=0.1.1"
+          ],
+          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7",
+          "version": "0.5.1"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
+              "url": "https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
+              "url": "https://files.pythonhosted.org/packages/a4/db/fffec68299e6d7bad3d504147f9094830b704527a7fc098b721d38cc7fa7/pyasn1-0.4.8.tar.gz"
+            }
+          ],
+          "project_name": "pyasn1",
+          "requires_dists": [],
+          "requires_python": null,
+          "version": "0.4.8"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9",
+              "url": "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206",
+              "url": "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz"
+            }
+          ],
+          "project_name": "pycparser",
+          "requires_dists": [],
+          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7",
+          "version": "2.21"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "8935bd4920ab9abfebb07c41a4f58296407ed77f04bd1a92914044b848ba1ed6",
+              "url": "https://files.pythonhosted.org/packages/85/3a/fe3c98435856a1ed798977981f3da82d2685cf9df97e4d9546340d2b83db/pyOpenSSL-21.0.0-py2.py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "5e2d8c5e46d0d865ae933bef5230090bdaf5506281e9eec60fa250ee80600cb3",
+              "url": "https://files.pythonhosted.org/packages/54/9a/2a43c5dbf4507f86f7c43cba4195d5e25a81c988fd7b0ea779dfc9c6973f/pyOpenSSL-21.0.0.tar.gz"
+            }
+          ],
+          "project_name": "pyopenssl",
+          "requires_dists": [
+            "cryptography>=3.3",
+            "flaky; extra == \\"test\\"",
+            "pretend; extra == \\"test\\"",
+            "pytest>=3.0.1; extra == \\"test\\"",
+            "six>=1.5.2",
+            "sphinx-rtd-theme; extra == \\"docs\\"",
+            "sphinx; extra == \\"docs\\""
+          ],
+          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7",
+          "version": "21"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "66cbb850987e47177a3b4112392490bcb76eb75b37cc53da007e35f3ec894bc1",
+              "url": "https://files.pythonhosted.org/packages/32/0e/11cfb3a5e269605d0bbe3bbca9845da9b57aed90e75bd489e5e7e3509c13/requests-2.5.0-py2.py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "d2daef4919fc87262b8b3cb5a9d214cac8ce1e50950f8423bbc1d31c2e63d38e",
+              "url": "https://files.pythonhosted.org/packages/c8/fb/d14d1c5166a8449d36c9a3b2656706c506a2cf261d37a79d16c18c37b646/requests-2.5.0.tar.gz"
+            }
+          ],
+          "project_name": "requests",
+          "requires_dists": [
+            "ndg-httpsclient; extra == \\"security\\"",
+            "pyOpenSSL; extra == \\"security\\"",
+            "pyasn1; extra == \\"security\\""
+          ],
+          "requires_python": null,
+          "version": "2.5"
+        },
+        {
+          "artifacts": [
+            {
+              "algorithm": "sha256",
+              "hash": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254",
+              "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl"
+            },
+            {
+              "algorithm": "sha256",
+              "hash": "1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+              "url": "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz"
+            }
+          ],
+          "project_name": "six",
+          "requires_dists": [],
+          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7",
+          "version": "1.16"
+        }
+      ],
+      "platform_tag": [
+        "cp310",
+        "cp310",
+        "manylinux_2_35_x86_64"
+      ]
+    }
+  ],
+  "pex_version": "2.1.73",
+  "prefer_older_binary": false,
+  "requirements": [
+    "requests[security]==2.5.0"
+  ],
+  "requires_python": [
+    "==3.9.*"
+  ],
+  "resolver_version": "pip-2020-resolver",
+  "style": "universal",
+  "transitive": true,
+  "use_pep517": null
+}
+"""
+
+# N.B.: These two locks have the same contents but differing artifact order. The Pip legacy resolver
+# sorts cffi and cryptography mac wheels before win, and the 2020 resolver does the reverse.
+EXPECTED_LOCKFILES = {
+    ResolverVersion.PIP_LEGACY: lockfile.loads(LEGACY_UNIVERSAL_LOCKFILE_CONTENTS),
+    ResolverVersion.PIP_2020: lockfile.loads(PIP_2020_UNIVERSAL_LOCKFILE_CONTENTS),
+}
 
 
 @pytest.mark.skipif(
     PY_VER < (3, 6),
     reason="Some sdists in this lock use f-strings in their builds which requires >=3.6",
 )
-def test_universal_lock(tmpdir):
-    # type: (Any) -> None
+@pytest.mark.parametrize(
+    ["resolver_version", "expected_lockfile"],
+    [
+        pytest.param(
+            resolver_version, EXPECTED_LOCKFILES.get(resolver_version), id=resolver_version.value
+        )
+        for resolver_version in ResolverVersion.values()
+    ],
+)
+def test_universal_lock(
+    tmpdir,  # type: Any
+    resolver_version,  # type: ResolverVersion.Value
+    expected_lockfile,  # type: Lockfile
+):
+    # type: (...) -> None
 
     constraints_file = os.path.join(str(tmpdir), "constraints.txt")
     with open(constraints_file, "w") as fp:
@@ -1063,6 +1395,8 @@ def test_universal_lock(tmpdir):
         "create",
         "--style",
         "universal",
+        "--resolver-version",
+        resolver_version.value,
         "--interpreter-constraint",
         "==3.9.*",
         "requests[security]==2.5.0",
@@ -1076,11 +1410,11 @@ def test_universal_lock(tmpdir):
     platform_tag = PythonInterpreter.get().identity.supported_tags[0]
     assert (
         attr.evolve(
-            UNIVERSAL_LOCKFILE,
+            expected_lockfile,
             pex_version=__version__,
             locked_resolves=SortedTuple(
                 attr.evolve(locked_resolve, platform_tag=platform_tag)
-                for locked_resolve in UNIVERSAL_LOCKFILE.locked_resolves
+                for locked_resolve in expected_lockfile.locked_resolves
             ),
         )
         == lock