Repository: pypa/wheel

Issue:
C-extension unable to be built on 3.13a1 (Windows)
Hello, I'm one of the maintainers of pygame-ce. I downloaded the recent release of Python 3.13a1 to test if pygame-ce would build against it, and after I commented out all the cython modules (which all failed to build ofc), I got this error:

```py
Traceback (most recent call last):
  File "<string>", line 2, in <module>
  File "<pip-setuptools-caller>", line 34, in <module>
  File "C:\Users\charl\Desktop\pygame-ce\setup.py", line 1051, in <module>
    setup(**PACKAGEDATA)
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\setuptools\_distutils\core.py", line 185, in setup
    return run_commands(dist)
            ^^^^^^^^^^^^^^^^^^
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\setuptools\_distutils\core.py", line 201, in run_commands
    dist.run_commands()
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\setuptools\_distutils\dist.py", line 969, in run_commands
    self.run_command(cmd)
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\setuptools\dist.py", line 989, in run_command
    super().run_command(command)
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\setuptools\_distutils\dist.py", line 988, in run_command
    cmd_obj.run()
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\wheel\bdist_wheel.py", line 401, in run
    impl_tag, abi_tag, plat_tag = self.get_tag()
                                  ^^^^^^^^^^^^^^
  File "C:\Users\charl\AppData\Local\Programs\Python\Python313\Lib\site-packages\wheel\bdist_wheel.py", line 351, in get_tag
    tag in supported_tags
AssertionError: would build wheel with unsupported tag ('cp313', 'cpwin_amd64', 'win_amd64')
```

I added a print for the supported tags and I got this: 
```
[('cp313', 'cp313', 'win_amd64'), ('cp313', 'abi3', 'win_amd64'), ('cp313', 'none', 'win_amd64'), ('cp312', 'abi3', 'win_amd64'), ('cp311', 'abi3', 'win_amd64'), ('cp310', 'abi3', 'win_amd64'), ('cp39', 'abi3', 'win_amd64'), ('cp38', 'abi3', 'win_amd64'), ('cp37', 'abi3', 'win_amd64'), ('cp36', 'abi3', 'win_amd64'), ('cp35', 'abi3', 'win_amd64'), ('cp34', 'abi3', 'win_amd64'), ('cp33', 'abi3', 'win_amd64'), ('cp32', 'abi3', 'win_amd64'), ('py313', 'none', 'win_amd64'), ('py3', 'none', 'win_amd64'), ('py312', 'none', 'win_amd64'), ('py311', 'none', 'win_amd64'), ('py310', 'none', 'win_amd64'), ('py39', 'none', 'win_amd64'), ('py38', 'none', 'win_amd64'), ('py37', 'none', 'win_amd64'), ('py36', 'none', 'win_amd64'), ('py35', 'none', 'win_amd64'), ('py34', 'none', 'win_amd64'), ('py33', 'none', 'win_amd64'), ('py32', 'none', 'win_amd64'), ('py31', 'none', 'win_amd64'), ('py30', 'none', 'win_amd64'), ('cp313', 'none', 'win_amd64'), ('py313', 'none', 'win_amd64'), ('py3', 'none', 'win_amd64'), ('py312', 'none', 'win_amd64'), ('py311', 'none', 'win_amd64'), ('py310', 'none', 'win_amd64'), ('py39', 'none', 'win_amd64'), ('py38', 'none', 'win_amd64'), ('py37', 'none', 'win_amd64'), ('py36', 'none', 'win_amd64'), ('py35', 'none', 'in_amd64')]
```

Since pygame-ce is a C-extension and is not using the limited ABI, the correct abi_tag is "cp313." I tried going into bdist_wheel.py and hardcoding that and the build worked completely.

Why has this changed?

I looked at the logic to get the wheel tag and noticed that on Python 3.12, `sysconfig.get_config_var("SOABI")` returns `None`, but on Python 3.13a1 `sysconfig.get_config_var("SOABI")` returns `'cp313-win_amd64'`. This causes an invalid abi_tag to be generated and the build won't complete.

The only other mention I was able to find of this on the internet was this Chinese forum post with someone unable to install PyQt5 with the same error message- https://ask.csdn.net/questions/8011982

I'm unsure if this would be considered a bug in CPython for the behavior change or a bug in wheel for not accommodating it. I'm putting it here for now.

Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/pypa/wheel/pull/578?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa) Report
All modified lines are covered by tests :white_check_mark:
> Comparison is base [(`dc1b9f9`)](https://app.codecov.io/gh/pypa/wheel/commit/dc1b9f9008d28f63258e9cb59014e9a48d2649ab?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa) 72.61% compared to head [(`67df599`)](https://app.codecov.io/gh/pypa/wheel/pull/578?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa) 71.26%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #578      +/-   ##
==========================================
- Coverage   72.61%   71.26%   -1.35%     
==========================================
  Files          13       13              
  Lines        1088     1079       -9     
==========================================
- Hits          790      769      -21     
- Misses        298      310      +12     
```


| [Files](https://app.codecov.io/gh/pypa/wheel/pull/578?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa) | Coverage Δ | |
|---|---|---|
| [src/wheel/bdist\_wheel.py](https://app.codecov.io/gh/pypa/wheel/pull/578?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa#diff-c3JjL3doZWVsL2JkaXN0X3doZWVsLnB5) | `53.09% <100.00%> (-3.63%)` | :arrow_down: |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/pypa/wheel/pull/578/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/pypa/wheel/pull/578?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pypa).

agronholm: Would you mind adding a changelog entry?

Patch:
diff --git a/docs/news.rst b/docs/news.rst
index 9e5488a..05763f4 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -1,6 +1,10 @@
 Release Notes
 =============
 
+**UNRELEASED**
+
+- Fixed ABI tag generation for CPython 3.13a1 on Windows (PR by Sam Gross)
+
 **0.41.2 (2023-08-22)**
 
 - Fixed platform tag detection for GraalPy and 32-bit python running on an aarch64
diff --git a/src/wheel/bdist_wheel.py b/src/wheel/bdist_wheel.py
index 586d876..3879019 100644
--- a/src/wheel/bdist_wheel.py
+++ b/src/wheel/bdist_wheel.py
@@ -117,8 +117,12 @@ def get_abi_tag():
             m = "m"
 
         abi = f"{impl}{tags.interpreter_version()}{d}{m}{u}"
-    elif soabi and impl == "cp":
+    elif soabi and impl == "cp" and soabi.startswith("cpython"):
+        # non-Windows
         abi = "cp" + soabi.split("-")[1]
+    elif soabi and impl == "cp" and soabi.startswith("cp"):
+        # Windows
+        abi = soabi.split("-")[0]
     elif soabi and impl == "pp":
         # we want something like pypy36-pp73
         abi = "-".join(soabi.split("-")[:2])


Test patch:
diff --git a/tests/test_bdist_wheel.py b/tests/test_bdist_wheel.py
index cebe0a3..7c8fedb 100644
--- a/tests/test_bdist_wheel.py
+++ b/tests/test_bdist_wheel.py
@@ -287,6 +287,12 @@ def test_unix_epoch_timestamps(dummy_dist, monkeypatch, tmp_path):
     )
 
 
+def test_get_abi_tag_windows(monkeypatch):
+    monkeypatch.setattr(tags, "interpreter_name", lambda: "cp")
+    monkeypatch.setattr(sysconfig, "get_config_var", lambda x: "cp313-win_amd64")
+    assert get_abi_tag() == "cp313"
+
+
 def test_get_abi_tag_pypy_old(monkeypatch):
     monkeypatch.setattr(tags, "interpreter_name", lambda: "pp")
     monkeypatch.setattr(sysconfig, "get_config_var", lambda x: "pypy36-pp73")