99import json
1010import sys
1111from dataclasses import asdict , dataclass
12+ from datetime import datetime
1213from pathlib import Path
1314from typing import Any
1415from urllib .parse import quote
2021
2122INDEX_HTML_TEMPLATE = """<!DOCTYPE html>
2223<html>
24+ <!-- {comment} -->
2325 <meta name="pypi:repository-version" content="1.0">
2426 <body>
2527{items}
@@ -90,19 +92,22 @@ def parse_from_filename(file: str) -> WheelFileInfo:
9092 )
9193
9294
93- def generate_project_list (subdir_names : list [str ]) -> str :
95+ def generate_project_list (subdir_names : list [str ], comment : str = "" ) -> str :
9496 """
9597 Generate project list HTML content linking to each project & variant sub-directory.
9698 """
9799 href_tags = []
98100 for name in sorted (subdir_names ):
99101 name = name .strip ("/" ).strip ("." )
100102 href_tags .append (f' <a href="{ name } /">{ name } /</a><br/>' )
101- return INDEX_HTML_TEMPLATE .format (items = "\n " .join (href_tags ))
103+ return INDEX_HTML_TEMPLATE .format (items = "\n " .join (href_tags ), comment = comment )
102104
103105
104106def generate_package_index_and_metadata (
105- wheel_files : list [WheelFileInfo ], wheel_base_dir : Path , index_base_dir : Path
107+ wheel_files : list [WheelFileInfo ],
108+ wheel_base_dir : Path ,
109+ index_base_dir : Path ,
110+ comment : str = "" ,
106111) -> tuple [str , str ]:
107112 """
108113 Generate package index HTML content for a specific package, linking to actual wheel files.
@@ -120,7 +125,7 @@ def generate_package_index_and_metadata(
120125 file_meta = asdict (file )
121126 file_meta ["path" ] = file_path_quoted
122127 metadata .append (file_meta )
123- index_str = INDEX_HTML_TEMPLATE .format (items = "\n " .join (href_tags ))
128+ index_str = INDEX_HTML_TEMPLATE .format (items = "\n " .join (href_tags ), comment = comment )
124129 metadata_str = json .dumps (metadata , indent = 2 )
125130 return index_str , metadata_str
126131
@@ -131,6 +136,7 @@ def generate_index_and_metadata(
131136 index_base_dir : Path ,
132137 default_variant : str | None = None ,
133138 alias_to_default : str | None = None ,
139+ comment : str = "" ,
134140):
135141 """
136142 Generate index for all wheel files.
@@ -141,6 +147,7 @@ def generate_index_and_metadata(
141147 index_base_dir (Path): Base directory to store index files.
142148 default_variant (str | None): The default variant name, if any.
143149 alias_to_default (str | None): Alias variant name for the default variant, if any.
150+ comment (str | None): Optional comment to include in the generated HTML files.
144151
145152 First, parse all wheel files to extract metadata.
146153 We need to collect all wheel files for each variant, and generate an index for it (in a sub-directory).
@@ -234,6 +241,10 @@ def generate_index_and_metadata(
234241 variant_to_files [alias_to_default ] = variant_to_files ["default" ].copy ()
235242 print (f"Alias variant '{ alias_to_default } ' created for default variant." )
236243
244+ # Generate comment in HTML header
245+ comment_str = f" ({ comment } )" if comment else ""
246+ comment_tmpl = f"Generated on { datetime .now ().isoformat ()} { comment_str } "
247+
237248 # Generate index for each variant
238249 subdir_names = set ()
239250 for variant , files in variant_to_files .items ():
@@ -253,7 +264,7 @@ def generate_index_and_metadata(
253264 subdir_names = subdir_names .union (packages )
254265 else :
255266 # generate project list for this variant directly
256- project_list_str = generate_project_list (sorted (packages ))
267+ project_list_str = generate_project_list (sorted (packages ), comment_tmpl )
257268 with open (variant_dir / "index.html" , "w" ) as f :
258269 f .write (project_list_str )
259270
@@ -263,15 +274,15 @@ def generate_index_and_metadata(
263274 package_dir = variant_dir / package
264275 package_dir .mkdir (parents = True , exist_ok = True )
265276 index_str , metadata_str = generate_package_index_and_metadata (
266- package_files , wheel_base_dir , package_dir
277+ package_files , wheel_base_dir , package_dir , comment
267278 )
268279 with open (package_dir / "index.html" , "w" ) as f :
269280 f .write (index_str )
270281 with open (package_dir / "metadata.json" , "w" ) as f :
271282 f .write (metadata_str )
272283
273284 # Generate top-level project list index
274- project_list_str = generate_project_list (sorted (subdir_names ))
285+ project_list_str = generate_project_list (sorted (subdir_names ), comment_tmpl )
275286 with open (index_base_dir / "index.html" , "w" ) as f :
276287 f .write (project_list_str )
277288
@@ -283,6 +294,7 @@ def generate_index_and_metadata(
283294 --current-objects <path_to_json> : path to JSON file containing current S3 objects listing in this version directory
284295 --output-dir <output_directory> : directory to store generated index files
285296 --alias-to-default <alias_variant_name> : (optional) alias variant name for the default variant
297+ --comment <comment_string> : (optional) comment string to include in generated HTML files
286298 """
287299
288300 parser = argparse .ArgumentParser (
@@ -312,6 +324,12 @@ def generate_index_and_metadata(
312324 default = None ,
313325 help = "Alias variant name for the default variant" ,
314326 )
327+ parser .add_argument (
328+ "--comment" ,
329+ type = str ,
330+ default = "" ,
331+ help = "Optional comment string to include in generated HTML files" ,
332+ )
315333
316334 args = parser .parse_args ()
317335
@@ -366,5 +384,6 @@ def generate_index_and_metadata(
366384 index_base_dir = index_base_dir ,
367385 default_variant = None ,
368386 alias_to_default = args .alias_to_default ,
387+ comment = args .comment .strip (),
369388 )
370389 print (f"Successfully generated index and metadata in { output_dir } " )
0 commit comments