22import datetime
33import logging
44import typing
5- from email .message import EmailMessage , Message
6- from email .parser import BytesParser
75from io import BytesIO
8- from typing import TYPE_CHECKING
96from zipfile import ZipFile
107
8+ from packaging .metadata import Metadata
119from packaging .requirements import Requirement
1210from packaging .utils import BuildTag , canonicalize_name
1311from packaging .version import Version
1614
1715logger = logging .getLogger (__name__ )
1816
19- # fix for runtime errors caused by inheriting classes that are generic in stubs but not runtime
20- # https://mypy.readthedocs.io/en/latest/runtime_troubles.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime
21- if TYPE_CHECKING :
22- Metadata = Message [str , str ]
23- else :
24- Metadata = Message
25-
2617
2718@dataclasses .dataclass (frozen = True , order = True , slots = True , repr = False , kw_only = True )
2819class Candidate :
@@ -73,11 +64,10 @@ def metadata(self) -> Metadata:
7364 return self ._metadata
7465
7566 def _get_dependencies (self ) -> typing .Iterable [Requirement ]:
76- deps = self .metadata .get_all ( "Requires-Dist" , [])
67+ deps = self .metadata .requires_dist or []
7768 extras = self .extras if self .extras else ["" ]
7869
79- for d in deps :
80- r = Requirement (d )
70+ for r in deps :
8171 if r .marker is None :
8272 yield r
8373 else :
@@ -95,7 +85,8 @@ def dependencies(self) -> list[Requirement]:
9585
9686 @property
9787 def requires_python (self ) -> str | None :
98- return self .metadata .get ("Requires-Python" )
88+ spec = self .metadata .requires_python
89+ return str (spec ) if spec is not None else None
9990
10091
10192def get_metadata_for_wheel (url : str , metadata_url : str | None = None ) -> Metadata :
@@ -107,7 +98,7 @@ def get_metadata_for_wheel(url: str, metadata_url: str | None = None) -> Metadat
10798 metadata_url: Optional URL of the metadata file (PEP 658)
10899
109100 Returns:
110- Parsed metadata as a Message object
101+ Parsed metadata as a Metadata object
111102 """
112103 # Try PEP 658 metadata endpoint first if available
113104 if metadata_url :
@@ -119,8 +110,7 @@ def get_metadata_for_wheel(url: str, metadata_url: str | None = None) -> Metadat
119110 response .raise_for_status ()
120111
121112 # Parse metadata directly from the response content
122- p = BytesParser ()
123- metadata = p .parse (BytesIO (response .content ), headersonly = True )
113+ metadata = Metadata .from_email (response .content )
124114 logger .debug (f"Successfully retrieved metadata via PEP 658 for { url } " )
125115 return metadata
126116
@@ -136,8 +126,8 @@ def get_metadata_for_wheel(url: str, metadata_url: str | None = None) -> Metadat
136126 with ZipFile (BytesIO (data )) as z :
137127 for n in z .namelist ():
138128 if n .endswith (".dist-info/METADATA" ):
139- p = BytesParser ( )
140- return p . parse ( z . open ( n ), headersonly = True )
129+ metadata_content = z . read ( n )
130+ return Metadata . from_email ( metadata_content )
141131
142- # If we didn't find the metadata, return an empty dict
143- return EmailMessage ( )
132+ # If we didn't find the metadata, raise an error
133+ raise ValueError ( f"Could not find METADATA file in wheel: { url } " )
0 commit comments