Repository: pypa/wheel

Issue:
"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.

Discussion:
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).


Patch:
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


Test patch:
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