|
1 | 1 | from abc import ABC, abstractproperty
|
2 |
| -from typing import Any, Dict, List, Optional |
| 2 | +from typing import Any, Dict, Iterator, List, Optional, cast |
3 | 3 |
|
4 | 4 | from packaging.requirements import Requirement
|
5 | 5 | from packaging.utils import NormalizedName, canonicalize_name
|
@@ -51,6 +51,10 @@ def __init__(self, data: Dict[str, Any]):
|
51 | 51 | def name(self) -> NormalizedName:
|
52 | 52 | return canonicalize_name(self.data["metadata"]["name"])
|
53 | 53 |
|
| 54 | + @property |
| 55 | + def metadata_name(self) -> str: |
| 56 | + return cast(str, self.data["metadata"]["name"]) |
| 57 | + |
54 | 58 | @property
|
55 | 59 | def version(self) -> str:
|
56 | 60 | version = self.data["metadata"]["version"]
|
@@ -83,8 +87,8 @@ def as_pip_requirement(self) -> str:
|
83 | 87 | """Convert to a pip requirement string."""
|
84 | 88 | direct_url = self.direct_url
|
85 | 89 | if direct_url is None:
|
86 |
| - return f"{self.name}=={self.version}" |
87 |
| - return direct_url.as_pip_requirement(self.name) |
| 90 | + return f"{self.metadata_name}=={self.version}" |
| 91 | + return direct_url.as_pip_requirement(self.metadata_name) |
88 | 92 |
|
89 | 93 |
|
90 | 94 | class EnvInfoInstalledDistribution(InstalledDistribution):
|
@@ -142,3 +146,11 @@ def __init__(self, data: Dict[str, Any], environment: Dict[str, str]):
|
142 | 146 |
|
143 | 147 |
|
144 | 148 | InstalledDistributions = Dict[NormalizedName, InstalledDistribution]
|
| 149 | + |
| 150 | + |
| 151 | +def installed_distributions_as_pip_requirements( |
| 152 | + installed_distributions: InstalledDistributions, |
| 153 | +) -> Iterator[str]: |
| 154 | + """Iterate installed distributions as pip frozen requirements.""" |
| 155 | + for _, dist in sorted(installed_distributions.items()): |
| 156 | + yield dist.as_pip_requirement() |
0 commit comments