Repository: pypa/pip

Issue:
22.1: Editable installs for packages with extras & flit causes `UndefinedEnvironmentName`
### Description

First of all, thanks for `pip` and for taking the time to read this issue!

We use editable installs on [sigstore-python](https://github.com/sigstore/sigstore-python) to provide a convenient development environment. For example, either with or without the `dev` extra:

```
pip install --editable .
pip install --editable .[dev]
```

Our dependencies are entirely managed within a `pyproject.toml`, with a small stub `setup.py` to help `pip` do an editable install.

Up until `pip==22.1`, these commands worked just fine. Upon upgrading to `22.1` (released today), we get this error:

```
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_vendor/packaging/markers.py", line 215, in _get_env
    raise UndefinedEnvironmentName(
pip._vendor.packaging.markers.UndefinedEnvironmentName: 'extra' does not exist in evaluation environment.
```

(I've truncated the traceback. I'll paste the full-length trace below.)

When I run with `--debug`, I see that the `dev` extra is being passed in as an environment marker, which then fails since `extra` is not included in the marker environment.

![image](https://user-images.githubusercontent.com/3059210/167964052-9a650ccc-8562-417e-bbe0-c9f5790738d2.png)

<img width="933" alt="Screen Shot 2022-05-11 at 7 34 06 PM" src="https://user-images.githubusercontent.com/3059210/167964111-4fef9399-51c8-4e82-9ed2-d1d31034dc46.png">



### Expected behavior

I expect `pip install --editable .` to behave the same as it did in the last stable release (22.0.4), i.e. install correctly with no errors.

### pip version

22.1

### Python version

3.10.0

### OS

macOS 12.3.1

### How to Reproduce

These steps should reproduce the failure:

```bash
git clone https://github.com/sigstore/sigstore-python && cd sigstore-python
make dev
```

If that fails to pull down the latest `pip` for whatever reason, you can do it explicitly:

```bash
git clone https://github.com/sigstore/sigstore-python && cd sigstore-python
python -m venv env && source env/bin/activate
pip install --upgrade pip
pip install --editable .
```

### Output

```sh-session
Obtaining file:///Users/william/devel/sigstore-python
  Installing build dependencies: started
  Installing build dependencies: finished with status 'done'
  Checking if build backend supports build_editable: started
  Checking if build backend supports build_editable: finished with status 'done'
  Getting requirements to build editable: started
  Getting requirements to build editable: finished with status 'done'
ERROR: Exception:
Traceback (most recent call last):
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/cli/base_command.py", line 167, in exc_logging_wrapper
    status = run_func(*args)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/cli/req_command.py", line 205, in wrapper
    return func(self, options, args)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/commands/install.py", line 340, in run
    requirement_set = resolver.resolve(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 75, in resolve
    collected = self.factory.collect_root_requirements(root_reqs)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 506, in collect_root_requirements
    req = self._make_requirement_from_install_req(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 468, in _make_requirement_from_install_req
    cand = self._make_candidate_from_link(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 188, in _make_candidate_from_link
    self._editable_candidate_cache[link] = EditableCandidate(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 316, in __init__
    super().__init__(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 161, in __init__
    self.dist = self._prepare()
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 230, in _prepare
    dist = self._prepare_distribution()
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 326, in _prepare_distribution
    return self._factory.preparer.prepare_editable_requirement(self._ireq)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 543, in prepare_editable_requirement
    dist = _get_prepared_distribution(
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 57, in _get_prepared_distribution
    abstract_dist.prepare_distribution_metadata(finder, build_isolation)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py", line 45, in prepare_distribution_metadata
    self._install_build_reqs(finder)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py", line 114, in _install_build_reqs
    conflicting, missing = self.req.build_env.check_requirements(build_reqs)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_internal/build_env.py", line 178, in check_requirements
    if req.marker is not None and not req.marker.evaluate():
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_vendor/packaging/markers.py", line 304, in evaluate
    return _evaluate_markers(self._markers, current_environment)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_vendor/packaging/markers.py", line 234, in _evaluate_markers
    lhs_value = _get_env(environment, lhs.value)
  File "/Users/william/devel/sigstore-python/env/lib/python3.10/site-packages/pip/_vendor/packaging/markers.py", line 215, in _get_env
    raise UndefinedEnvironmentName(
pip._vendor.packaging.markers.UndefinedEnvironmentName: 'extra' does not exist in evaluation environment.
```


### Code of Conduct

- [X] I agree to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/).


Discussion:

Resolving patch:
diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py
--- a/src/pip/_internal/build_env.py
+++ b/src/pip/_internal/build_env.py
@@ -175,8 +175,10 @@ def check_requirements(
             )
             for req_str in reqs:
                 req = Requirement(req_str)
-                if req.marker is not None and not req.marker.evaluate():
-                    continue  # FIXME: Consider extras?
+                # We're explicitly evaluating with an empty extra value, since build
+                # environments are not provided any mechanism to select specific extras.
+                if req.marker is not None and not req.marker.evaluate({"extra": ""}):
+                    continue
                 dist = env.get_distribution(req.name)
                 if not dist:
                     missing.add(req_str)


Test patch:
diff --git a/tests/functional/test_build_env.py b/tests/functional/test_build_env.py
--- a/tests/functional/test_build_env.py
+++ b/tests/functional/test_build_env.py
@@ -178,6 +178,7 @@ def test_build_env_requirements_check(script: PipTestEnvironment) -> None:
             [
                 "bar==2.0; python_version < '3.0'",
                 "bar==3.0; python_version >= '3.0'",
+                "foo==4.0; extra == 'dev'",
             ],
         )
         assert r == (set(), set()), repr(r)