Repository: pex-tool/pex

Issue:
Can not create lock file when handling none ABI
Notice pants could not create a lock file when dealing with python-forge as a dependency. Pip seems to handle installing the package just fine.

See below
```
❯ python --version
Python 3.11.6
❯ pip install python-forge==18.6.0
Looking in indexes: https://pypi.org/simple/
Collecting python-forge==18.6.0
  Using cached python_forge-18.6.0-py35-none-any.whl (31 kB)
Installing collected packages: python-forge
Successfully installed python-forge-18.6.0
❯ pip --version
pip 23.2.1 from /Users/user/throwaway/lib/python3.11/site-packages/pip (python 3.11)
```
Notice python-forge's wheel file is: [python_forge-18.6.0-py35-none-any.whl ](https://pypi.org/project/python-forge/#files)


Discussion:
More context on this failure here: https://pantsbuild.slack.com/archives/C046T6T9U/p1697560578590339

Resolving patch:
diff --git a/pex/resolve/locker_patches.py b/pex/resolve/locker_patches.py
--- a/pex/resolve/locker_patches.py
+++ b/pex/resolve/locker_patches.py
@@ -93,7 +93,9 @@ def patch_wheel_model():
         def supported_version(self, *_args, **_kwargs):
             if not hasattr(self, "_versions"):
                 versions = set()
-                is_abi3 = ["abi3"] == list(self.abis)
+                abis = list(self.abis)
+                is_abi3 = ["abi3"] == abis
+                is_abi_none = ["none"] == abis
                 for pyversion in self.pyversions:
                     # For the format, see: https://peps.python.org/pep-0425/#python-tag
                     match = re.search(r"^(?P<impl>\D{2,})(?P<major>\d)(?P<minor>\d+)?", pyversion)
@@ -106,7 +108,7 @@ def supported_version(self, *_args, **_kwargs):
 
                     major = int(match.group("major"))
                     minor = match.group("minor")
-                    if is_abi3 and major == 3:
+                    if is_abi_none or (is_abi3 and major == 3):
                         versions.add(major)
                     elif minor:
                         versions.add((major, int(minor)))


Test patch:
diff --git a/tests/integration/cli/commands/test_issue_2268.py b/tests/integration/cli/commands/test_issue_2268.py
new file mode 100644
--- /dev/null
+++ b/tests/integration/cli/commands/test_issue_2268.py
@@ -0,0 +1,74 @@
+# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
+# Licensed under the Apache License, Version 2.0 (see LICENSE).
+import os.path
+import sys
+
+import pytest
+
+from pex.compatibility import commonpath
+from pex.resolve.resolver_configuration import ResolverVersion
+from pex.typing import TYPE_CHECKING
+from testing import run_pex_command
+from testing.cli import run_pex3
+
+if TYPE_CHECKING:
+    from typing import Any
+
+
+@pytest.mark.skipif(
+    sys.version_info[:2] < (3, 5),
+    reason=(
+        "This test relies on the python-forge 18.6.0 offering only the single "
+        "python_forge-18.6.0-py35-none-any.whl distribution on PyPI and this wheel only works for "
+        "Python 3.5 and greater"
+    ),
+)
+@pytest.mark.parametrize(
+    "resolver_version",
+    [
+        pytest.param(resolver_version, id=str(resolver_version))
+        for resolver_version in ResolverVersion.values()
+        if ResolverVersion.applies(resolver_version)
+    ],
+)
+def test_abi_none_locking(
+    tmpdir,  # type: Any
+    resolver_version,  # type: ResolverVersion.Value
+):
+    # type: (...) -> None
+
+    pex_root = os.path.join(str(tmpdir), "pex_root")
+    lock = os.path.join(str(tmpdir), "lock.json")
+    run_pex3(
+        "lock",
+        "create",
+        "--style",
+        "universal",
+        "--resolver-version",
+        str(resolver_version),
+        "--interpreter-constraint",
+        "==3.11.*",
+        "python-forge==18.6.0",
+        "-o",
+        lock,
+        "--indent",
+        "2",
+        "--pex-root",
+        pex_root,
+    ).assert_success()
+
+    result = run_pex_command(
+        args=[
+            "--pex-root",
+            pex_root,
+            "--runtime-pex-root",
+            pex_root,
+            "--lock",
+            lock,
+            "--",
+            "-c",
+            "import forge; print(forge.__file__)",
+        ]
+    )
+    result.assert_success()
+    assert pex_root == commonpath([pex_root, result.output.strip()])
diff --git a/tests/integration/test_issue_539.py b/tests/integration/test_issue_539.py
--- a/tests/integration/test_issue_539.py
+++ b/tests/integration/test_issue_539.py
@@ -9,6 +9,7 @@
 
 from pex.common import temporary_dir
 from pex.pip.installation import get_pip
+from pex.resolve.configured_resolver import ConfiguredResolver
 from testing import IS_LINUX_ARM64, IS_PYPY, PY_VER, run_pex_command
 
 
@@ -35,11 +36,12 @@ def test_abi3_resolution():
         # sdist. Since we want to test in --no-build, we pre-resolve/build the pycparser wheel here and
         # add the resulting wheelhouse to the --no-build pex command.
         download_dir = os.path.join(td, ".downloads")
-        get_pip().spawn_download_distributions(
+        pip = get_pip(resolver=ConfiguredResolver.default())
+        pip.spawn_download_distributions(
             download_dir=download_dir, requirements=["pycparser"]
         ).wait()
         wheel_dir = os.path.join(td, ".wheels")
-        get_pip().spawn_build_wheels(
+        pip.spawn_build_wheels(
             wheel_dir=wheel_dir, distributions=glob.glob(os.path.join(download_dir, "*"))
         ).wait()