Repository: pypa/virtualenv

Issue:
pinning pip fails via app data seeder
```
VIRTUALENV_PIP=19.2.3 virtualenv --download --seeder app-data .venv
ERROR: Invalid requirement: 'pip=19.2.3'
```

from https://github.com/pglass/tox-pip-version/issues/17#issuecomment-616246861


Discussion:

Resolving patch:
diff --git a/src/virtualenv/seed/embed/wheels/acquire.py b/src/virtualenv/seed/embed/wheels/acquire.py
--- a/src/virtualenv/seed/embed/wheels/acquire.py
+++ b/src/virtualenv/seed/embed/wheels/acquire.py
@@ -129,7 +129,7 @@ def _get_wheels(from_folder, packages):
 
 
 def download_wheel(packages, for_py_version, to_folder, app_data):
-    to_download = list(p if v is None else "{}={}".format(p, v) for p, v in packages.items())
+    to_download = list(p if v is None else "{}=={}".format(p, v) for p, v in packages.items())
     logging.debug("download wheels %s", to_download)
     cmd = [
         sys.executable,
diff --git a/src/virtualenv/util/path/_pathlib/via_os_path.py b/src/virtualenv/util/path/_pathlib/via_os_path.py
--- a/src/virtualenv/util/path/_pathlib/via_os_path.py
+++ b/src/virtualenv/util/path/_pathlib/via_os_path.py
@@ -111,9 +111,9 @@ def open(self, mode="r"):
     def parents(self):
         result = []
         parts = self.parts
-        for i in range(len(parts)):
+        for i in range(len(parts) - 1):
             result.append(Path(os.sep.join(parts[0 : i + 1])))
-        return result
+        return result[::-1]
 
     def unlink(self):
         os.remove(self._path)


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -212,36 +212,25 @@ def finish():
 
 class EnableCoverage(object):
     _COV_FILE = Path(coverage.__file__)
-    _COV_SITE_PACKAGES = _COV_FILE.parents[1]
-    _ROOT_COV_FILES_AND_FOLDERS = [i for i in _COV_SITE_PACKAGES.iterdir() if i.name.startswith("coverage")]
-    _SUBPROCESS_TRIGGER_PTH_NAME = "coverage-virtual-sub.pth"
+    _ROOT_COV_FILES_AND_FOLDERS = [i for i in _COV_FILE.parents[1].iterdir() if i.name.startswith("coverage")]
 
     def __init__(self, link):
         self.link = link
         self.targets = []
-        self.cov_pth = self._COV_SITE_PACKAGES / self._SUBPROCESS_TRIGGER_PTH_NAME
 
     def __enter__(self, creator):
-        assert not self.cov_pth.exists()
         site_packages = creator.purelib
-        p_th = site_packages / self._SUBPROCESS_TRIGGER_PTH_NAME
-
-        if not str(p_th).startswith(str(self._COV_SITE_PACKAGES)):
-            p_th.write_text("import coverage; coverage.process_startup()")
-            self.targets.append((p_th, p_th.unlink))
-            for entry in self._ROOT_COV_FILES_AND_FOLDERS:
-                target = site_packages / entry.name
-                if not target.exists():
-                    clean = self.link(entry, target)
-                    self.targets.append((target, clean))
+        for entry in self._ROOT_COV_FILES_AND_FOLDERS:
+            target = site_packages / entry.name
+            if not target.exists():
+                clean = self.link(entry, target)
+                self.targets.append((target, clean))
         return self
 
     def __exit__(self, exc_type, exc_val, exc_tb):
-        assert self._COV_FILE.exists()
         for target, clean in self.targets:
             if target.exists():
                 clean()
-        assert not self.cov_pth.exists()
         assert self._COV_FILE.exists()
 
 
diff --git a/tests/integration/test_run_int.py b/tests/integration/test_run_int.py
new file mode 100644
--- /dev/null
+++ b/tests/integration/test_run_int.py
@@ -0,0 +1,19 @@
+from __future__ import absolute_import, unicode_literals
+
+from virtualenv import cli_run
+from virtualenv.util.six import ensure_text
+from virtualenv.util.subprocess import run_cmd
+
+
+def test_app_data_pinning(tmp_path):
+    result = cli_run([ensure_text(str(tmp_path)), "--pip", "19.3.1", "--activators", "", "--seeder", "app-data"])
+    code, out, err = run_cmd([str(result.creator.script("pip")), "list", "--disable-pip-version-check"])
+    assert not code
+    assert not err
+    for line in out.splitlines():
+        parts = line.split()
+        if parts and parts[0] == "pip":
+            assert parts[1] == "19.3.1"
+            break
+    else:
+        assert not out
diff --git a/tests/unit/create/test_creator.py b/tests/unit/create/test_creator.py
--- a/tests/unit/create/test_creator.py
+++ b/tests/unit/create/test_creator.py
@@ -395,7 +395,6 @@ def test_create_long_path(current_fastest, tmp_path):
     subprocess.check_call([str(result.creator.script("pip")), "--version"])
 
 
-@pytest.mark.timeout(timeout=60)
 @pytest.mark.parametrize("creator", set(PythonInfo.current_system().creators().key_to_class) - {"builtin"})
 def test_create_distutils_cfg(creator, tmp_path, monkeypatch):
     result = cli_run([ensure_text(str(tmp_path / "venv")), "--activators", "", "--creator", creator])