593bff23edecd3c517c96e119ee777bd4ee1d9d0
[SubU] /
1 import importlib.metadata
2 from typing import Any, Optional, Protocol, cast
3
4
5 class BadMetadata(ValueError):
6     def __init__(self, dist: importlib.metadata.Distribution, *, reason: str) -> None:
7         self.dist = dist
8         self.reason = reason
9
10     def __str__(self) -> str:
11         return f"Bad metadata in {self.dist} ({self.reason})"
12
13
14 class BasePath(Protocol):
15     """A protocol that various path objects conform.
16
17     This exists because importlib.metadata uses both ``pathlib.Path`` and
18     ``zipfile.Path``, and we need a common base for type hints (Union does not
19     work well since ``zipfile.Path`` is too new for our linter setup).
20
21     This does not mean to be exhaustive, but only contains things that present
22     in both classes *that we need*.
23     """
24
25     @property
26     def name(self) -> str:
27         raise NotImplementedError()
28
29     @property
30     def parent(self) -> "BasePath":
31         raise NotImplementedError()
32
33
34 def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]:
35     """Find the path to the distribution's metadata directory.
36
37     HACK: This relies on importlib.metadata's private ``_path`` attribute. Not
38     all distributions exist on disk, so importlib.metadata is correct to not
39     expose the attribute as public. But pip's code base is old and not as clean,
40     so we do this to avoid having to rewrite too many things. Hopefully we can
41     eliminate this some day.
42     """
43     return getattr(d, "_path", None)
44
45
46 def get_dist_name(dist: importlib.metadata.Distribution) -> str:
47     """Get the distribution's project name.
48
49     The ``name`` attribute is only available in Python 3.10 or later. We are
50     targeting exactly that, but Mypy does not know this.
51     """
52     name = cast(Any, dist).name
53     if not isinstance(name, str):
54         raise BadMetadata(dist, reason="invalid metadata entry 'name'")
55     return name