codecov[bot]: # [Codecov](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=h1) Report
> Merging [#213](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=desc) into [master](https://codecov.io/gh/pypa/wheel/commit/d120bf93a6ef38a8eae9580f18878ae8a29b4787?src=pr&el=desc) will **decrease** coverage by `0.04%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pypa/wheel/pull/213/graphs/tree.svg?width=650&height=150&src=pr&token=ey5B5hA7sW)](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #213      +/-   ##
==========================================
- Coverage   69.84%   69.79%   -0.05%     
==========================================
  Files          17       17              
  Lines        1817     1814       -3     
==========================================
- Hits         1269     1266       -3     
  Misses        548      548
```


| [Impacted Files](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [wheel/metadata.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvbWV0YWRhdGEucHk=) | `91.38% <100%> (+2.39%)` | :arrow_up: |
| [wheel/pep425tags.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvcGVwNDI1dGFncy5weQ==) | `83.01% <0%> (-4.72%)` | :arrow_down: |
| [wheel/install.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvaW5zdGFsbC5weQ==) | `80.14% <0%> (-0.44%)` | :arrow_down: |
| [wheel/tool/\_\_init\_\_.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvdG9vbC9fX2luaXRfXy5weQ==) | `35.47% <0%> (-0.43%)` | :arrow_down: |
| [wheel/wininst2wheel.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvd2luaW5zdDJ3aGVlbC5weQ==) | `16.66% <0%> (+0.13%)` | :arrow_up: |
| [wheel/egg2wheel.py](https://codecov.io/gh/pypa/wheel/pull/213/diff?src=pr&el=tree#diff-d2hlZWwvZWdnMndoZWVsLnB5) | `65.62% <0%> (+1%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=footer). Last update [d120bf9...61b1df5](https://codecov.io/gh/pypa/wheel/pull/213?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/CHANGES.txt b/CHANGES.txt
index 5c3ceee..a182ed7 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,7 @@
 Unreleased
 ==========
 - Fixed displaying of errors on Python 3
+- Fixed single digit versions in wheel files not being properly recognized
 
 0.30.0
 ======
diff --git a/wheel/install.py b/wheel/install.py
index 5c3e3d9..3d71d3d 100644
--- a/wheel/install.py
+++ b/wheel/install.py
@@ -34,9 +34,8 @@ VERSION_TOO_HIGH = (1, 0)
 # Non-greedy matching of an optional build number may be too clever (more
 # invalid wheel filenames will match). Separate regex for .dist-info?
 WHEEL_INFO_RE = re.compile(
-    r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>\d.+?))?)
-    ((-(?P<build>\d.*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
-    \.whl|\.dist-info)$""",
+    r"""^(?P<namever>(?P<name>.+?)-(?P<ver>\d.*?))(-(?P<build>\d.*?))?
+     -(?P<pyver>[a-z].+?)-(?P<abi>.+?)-(?P<plat>.+?)(\.whl|\.dist-info)$""",
     re.VERBOSE).match
 
 
diff --git a/wheel/metadata.py b/wheel/metadata.py
index 29638e7..75dce67 100644
--- a/wheel/metadata.py
+++ b/wheel/metadata.py
@@ -255,7 +255,7 @@ def generate_requirements(extras_require):
         if extra:
             yield ('Provides-Extra', extra)
             if condition:
-                condition += " and "
+                condition = "(" + condition + ") and "
             condition += "extra == '%s'" % extra
         if condition:
             condition = '; ' + condition

"and extra" breaks environment marker logic
In pypa/setuptools#1242, we discovered that wheel is allegedly simply appending ` and extra=="..."`, which will break the logic when the existing environment marker contains or expressions.
diff --git a/tests/test_install.py b/tests/test_install.py
index 60b04e8..42db4f0 100644
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -100,3 +100,9 @@ def test_install():
 def test_install_tool():
     """Slightly improve coverage of wheel.install"""
     wheel.tool.install([TESTWHEEL], force=True, dry_run=True)
+
+
+def test_wheelfile_re():
+    # Regression test for #208
+    wf = WheelFile('foo-2-py3-none-any.whl')
+    assert wf.distinfo_name == 'foo-2.dist-info'
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
new file mode 100644
index 0000000..842d1d3
--- /dev/null
+++ b/tests/test_metadata.py
@@ -0,0 +1,25 @@
+from wheel.metadata import generate_requirements
+
+
+def test_generate_requirements():
+    extras_require = {
+        'test': ['ipykernel', 'ipython', 'mock'],
+        'test:python_version == "3.3"': ['pytest<3.3.0'],
+        'test:python_version >= "3.4" or python_version == "2.7"': ['pytest'],
+    }
+    expected_metadata = [
+        ('Provides-Extra',
+         'test'),
+        ('Requires-Dist',
+         "ipykernel; extra == 'test'"),
+        ('Requires-Dist',
+         "ipython; extra == 'test'"),
+        ('Requires-Dist',
+         "mock; extra == 'test'"),
+        ('Requires-Dist',
+         'pytest (<3.3.0); (python_version == "3.3") and extra == \'test\''),
+        ('Requires-Dist',
+         'pytest; (python_version >= "3.4" or python_version == "2.7") and extra == \'test\''),
+    ]
+    generated_metadata = sorted(set(generate_requirements(extras_require)))
+    assert generated_metadata == expected_metadata

pip install -e .[tool]
parse_log_pytest
pytest pytest-cov
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
coverage==6.2
importlib-metadata==4.8.3
iniconfig==1.1.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: wheel
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - coverage==6.2
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/wheel

tests/test_install.py::test_wheelfile_re tests/test_metadata.py::test_generate_requirements
tests/test_install.py::test_compatibility_tags tests/test_install.py::test_pick_best tests/test_install.py::test_install tests/test_install.py::test_install_tool
CHANGES.txt wheel/metadata.py wheel/install.py
CHANGES.txt wheel/metadata.py wheel/install.py