This introduces an exception and presentation model, for providing
better errors messages. The motivating idea is that the better error
messages contain clear wording and provide additional context to users
to better understand what is happening.
The `DiagnosticPipError` class introduces a structured framework in our
exception model, for code authors to write their error messages. The
usage explicitly requires passing "context" and a "hint" (which accept
None values). This should nudge code authors to explicitly think about
what additional information can/should be presented to the user, and
to provide relevant hints to them whenever possible. It also makes it
straightforward to identify cases where we don't do this, which may
serve as clear areas for improvement in the future.
The initial implementation is intentionally basic and doesn't do much;
however we should be able to introduce better usage of terminal colors
and other features (eg: hyperlinks!) to further improve the presentation
of these errors. It does improve the presentation style by a bit, even
though there are significant presentation-related improvements to be
made.
Additionally, having a structured framework means that these would be
improvements in presentation of *all* the errors that are within this
framework -- increasing the benefits of investing in the presentation
of these errors.
towncrier renders with `trim_blocks=True` which trims the newline at the
start of the for loop's body. This adds an additional newline which is
not trimmed, which ensures that the code blocks don't blend into each
other.
Do not mention wheel, as this code path is also used
in legacy editable mode with isolation, where
no wheel is involved.
This also aligns with the new log entry for setup.py egg-info
which says "Preparing metadata (setup.py)".
When there is a pyproject.toml, metadata preparation must be
done in the isolated build environment for legacy editable installs too
(fixes a regression).
Also detect earlier if an editable install must go through the
legacy install path, to be sure to run it in an environment
with the correct build requirements.
This brings us in line with pre-platformdirs behaviours on these,
following the details of the configuration paths, as documented in pip's
own documentation.