1+ import hashlib
12import pkginfo
23import re
34import shutil
45import tempfile
6+ import zipfile
57import json
68from collections import defaultdict
79from django .conf import settings
@@ -130,7 +132,7 @@ def parse_project_metadata(project):
130132 # Release metadata
131133 "packagetype" : project .get ("packagetype" ) or "" ,
132134 "python_version" : project .get ("python_version" ) or "" ,
133- "metadata_sha256" : "" , # TODO
135+ "metadata_sha256" : project . get ( "metadata_sha256" ) or "" ,
134136 }
135137
136138
@@ -158,9 +160,9 @@ def parse_metadata(project, version, distribution):
158160 package ["url" ] = distribution .get ("url" ) or ""
159161 package ["sha256" ] = distribution .get ("digests" , {}).get ("sha256" ) or ""
160162 package ["python_version" ] = distribution .get ("python_version" ) or package .get ("python_version" )
161- package ["requires_python" ] = distribution .get ("requires_python" ) or package .get (
162- "requires_python"
163- ) # noqa: E501
163+ package ["requires_python" ] = distribution .get ("requires_python" ) or "" # package.get(
164+ # "requires_python"
165+ # ) # noqa: E501
164166 package ["metadata_sha256" ] = distribution .get ("data-dist-info-metadata" , {}).get (
165167 "sha256"
166168 ) or package .get ("metadata_sha256" )
@@ -181,6 +183,7 @@ def get_project_metadata_from_file(filename):
181183 packagetype = DIST_EXTENSIONS [extensions [pkg_type_index ]]
182184
183185 metadata = DIST_TYPES [packagetype ](filename )
186+ metadata .metadata_sha256 = compute_metadata_sha256 (filename )
184187 metadata .packagetype = packagetype
185188 if packagetype == "sdist" :
186189 metadata .python_version = "source"
@@ -193,6 +196,23 @@ def get_project_metadata_from_file(filename):
193196 return metadata
194197
195198
199+ def compute_metadata_sha256 (filename : str ) -> str :
200+ """
201+ Compute SHA256 hash of the metadata file from a Python package.
202+
203+ Returns SHA256 hash or empty string if metadata cannot be extracted.
204+ """
205+ if not filename .endswith (".whl" ):
206+ return ""
207+
208+ with zipfile .ZipFile (filename , "r" ) as f :
209+ for file_path in f .namelist ():
210+ if file_path .endswith (".dist-info/METADATA" ):
211+ metadata_content = f .read (file_path )
212+ return hashlib .sha256 (metadata_content ).hexdigest ()
213+ return ""
214+
215+
196216def artifact_to_python_content_data (filename , artifact , domain = None ):
197217 """
198218 Takes the artifact/filename and returns the metadata needed to create a PythonPackageContent.
@@ -448,7 +468,7 @@ def write_simple_detail_json(project_name, project_packages):
448468 "filename" : package ["filename" ],
449469 "url" : package ["url" ],
450470 "hashes" : {"sha256" : package ["sha256" ]},
451- "requires_python " : package ["requires_python" ] or None ,
471+ "requires-python " : package ["requires_python" ] or None ,
452472 # data-dist-info-metadata is deprecated alias for core-metadata
453473 "data-dist-info-metadata" : (
454474 {"sha256" : package ["metadata_sha256" ]} if package ["metadata_sha256" ] else False
0 commit comments