77import json
88from collections import defaultdict
99from django .conf import settings
10+ from django .utils import timezone
1011from jinja2 import Template
1112from packaging .utils import canonicalize_name
1213from packaging .requirements import Requirement
1819"""TODO This serial constant is temporary until Python repositories implements serials"""
1920PYPI_SERIAL_CONSTANT = 1000000000
2021
21- SIMPLE_API_VERSION = "1.0 "
22+ SIMPLE_API_VERSION = "1.1 "
2223
2324simple_index_template = """<!DOCTYPE html>
2425<html>
@@ -161,6 +162,7 @@ def parse_metadata(project, version, distribution):
161162 package ["sha256" ] = distribution .get ("digests" , {}).get ("sha256" ) or ""
162163 package ["python_version" ] = distribution .get ("python_version" ) or ""
163164 package ["requires_python" ] = distribution .get ("requires_python" ) or ""
165+ package ["size" ] = distribution .get ("size" ) or 0
164166
165167 return package
166168
@@ -223,6 +225,7 @@ def artifact_to_python_content_data(filename, artifact, domain=None):
223225 metadata = get_project_metadata_from_file (temp_file .name )
224226 data = parse_project_metadata (vars (metadata ))
225227 data ["sha256" ] = artifact .sha256
228+ data ["size" ] = artifact .size
226229 data ["filename" ] = filename
227230 data ["pulp_domain" ] = domain or artifact .pulp_domain
228231 data ["_pulp_domain" ] = data ["pulp_domain" ]
@@ -403,7 +406,6 @@ def find_artifact():
403406 components .insert (2 , domain .name )
404407 url = "/" .join (components )
405408 md5 = artifact .md5 if artifact and artifact .md5 else ""
406- size = artifact .size if artifact and artifact .size else 0
407409 return {
408410 "comment_text" : "" ,
409411 "digests" : {"md5" : md5 , "sha256" : content .sha256 },
@@ -414,7 +416,7 @@ def find_artifact():
414416 "packagetype" : content .packagetype ,
415417 "python_version" : content .python_version ,
416418 "requires_python" : content .requires_python or None ,
417- "size" : size ,
419+ "size" : content . size ,
418420 "upload_time" : str (content .pulp_created ),
419421 "upload_time_iso_8601" : str (content .pulp_created .isoformat ()),
420422 "url" : url ,
@@ -471,20 +473,32 @@ def write_simple_detail_json(project_name, project_packages):
471473 {"sha256" : package ["metadata_sha256" ]} if package ["metadata_sha256" ] else False
472474 ),
473475 # yanked and yanked_reason are not implemented because they are mutable
476+ # (v1.1, PEP 700)
477+ "size" : package ["size" ],
478+ "upload-time" : format_upload_time (package ["upload_time" ]),
474479 # TODO in the future:
475- # size, upload-time (v1.1, PEP 700)
476480 # core-metadata (PEP 7.14)
477481 # provenance (v1.3, PEP 740)
478482 }
479483 for package in project_packages
480484 ],
485+ # (v1.1, PEP 700)
486+ "versions" : sorted (set (package ["version" ] for package in project_packages )),
481487 # TODO in the future:
482- # versions (v1.1, PEP 700)
483488 # alternate-locations (v1.2, PEP 708)
484489 # project-status (v1.4, PEP 792 - pypi and docs differ)
485490 }
486491
487492
493+ def format_upload_time (upload_time ):
494+ """Formats the upload time to be in Zulu time. UTC with Z suffix"""
495+ if upload_time :
496+ if upload_time .tzinfo :
497+ dt = upload_time .astimezone (timezone .utc )
498+ return dt .isoformat ().replace ("+00:00" , "Z" )
499+ return None
500+
501+
488502class PackageIncludeFilter :
489503 """A special class to help filter Package's based on a remote's include/exclude"""
490504
0 commit comments