8686 "whl/test/variant" ,
8787 "whl/variant" ,
8888 "whl/preview/forge" ,
89+ "source_code/test" ,
8990]
9091
9192# NOTE: This refers to the name on the wheels themselves and not the name of
@@ -661,6 +662,21 @@ def to_libtorch_html(self, subdir: Optional[str] = None) -> str:
661662 out .append (f'<a href="/{ obj .key } ">{ sanitized_obj } </a><br/>' )
662663 return "\n " .join (sorted (out ))
663664
665+ def to_source_code_html (self , subdir : Optional [str ] = None ) -> str :
666+ """Generates a string that can be used as the HTML index for source code packages
667+
668+ Creates a simple browseable index for pytorch-*.tar.gz source code packages.
669+ """
670+ out : List [str ] = []
671+ subdir = self ._resolve_subdir (subdir )
672+ for obj in self .gen_file_list (subdir ):
673+ # Strip our prefix
674+ sanitized_obj = obj .key .replace (subdir , "" , 1 )
675+ if sanitized_obj .startswith ("/" ):
676+ sanitized_obj = sanitized_obj .lstrip ("/" )
677+ out .append (f'<a href="/{ obj .key } ">{ sanitized_obj } </a><br/>' )
678+ return "\n " .join (sorted (out ))
679+
664680 def to_simple_package_html (
665681 self ,
666682 subdir : Optional [str ],
@@ -804,6 +820,34 @@ def upload_libtorch_html(self) -> None:
804820 Body = index_html ,
805821 )
806822
823+ def upload_source_code_html (self ) -> None :
824+ """Upload source code index to S3 and R2"""
825+ # For source_code/test, it has a flat structure, so we only upload to the prefix directory
826+ index_html = self .to_source_code_html (subdir = self .prefix )
827+
828+ # Upload to S3
829+ print (
830+ f"INFO Uploading { self .prefix } /{ self .html_name } to S3 bucket { BUCKET .name } "
831+ )
832+ BUCKET .Object (key = f"{ self .prefix } /{ self .html_name } " ).put (
833+ ACL = "public-read" ,
834+ CacheControl = "no-cache,no-store,must-revalidate" ,
835+ ContentType = "text/html" ,
836+ Body = index_html ,
837+ )
838+
839+ # Upload to R2 if configured
840+ if R2_BUCKET :
841+ print (
842+ f"INFO Uploading { self .prefix } /{ self .html_name } to R2 bucket { R2_BUCKET .name } "
843+ )
844+ R2_BUCKET .Object (key = f"{ self .prefix } /{ self .html_name } " ).put (
845+ ACL = "public-read" ,
846+ CacheControl = "no-cache,no-store,must-revalidate" ,
847+ ContentType = "text/html" ,
848+ Body = index_html ,
849+ )
850+
807851 def upload_pep503_htmls (self ) -> None :
808852 # Pre-fetch bucket listings for all subdirectories to optimize S3 API calls
809853 print ("INFO: Pre-fetching S3 bucket listings for optimization..." )
@@ -970,6 +1014,15 @@ def save_libtorch_html(self) -> None:
9701014 ) as f :
9711015 f .write (self .to_libtorch_html (subdir = subdir ))
9721016
1017+ def save_source_code_html (self ) -> None :
1018+ """Save source code index to local file"""
1019+ print (f"INFO Saving { self .prefix } /{ self .html_name } " )
1020+ makedirs (self .prefix , exist_ok = True )
1021+ with open (
1022+ path .join (self .prefix , self .html_name ), mode = "w" , encoding = "utf-8"
1023+ ) as f :
1024+ f .write (self .to_source_code_html (subdir = self .prefix ))
1025+
9731026 def save_pep503_htmls (self ) -> None :
9741027 for subdir in self .subdirs :
9751028 print (f"INFO Saving { subdir } /index.html" )
@@ -1150,6 +1203,17 @@ def grant_public_read(cls, key: str) -> None:
11501203 @classmethod
11511204 def fetch_object_names (cls , prefix : str ) -> List [str ]:
11521205 obj_names = []
1206+
1207+ # Special handling for source_code prefix - flat structure with only tar.gz files
1208+ if prefix .startswith ("source_code" ):
1209+ for obj in BUCKET .objects .filter (Prefix = prefix ):
1210+ # For source_code, we only want files directly in the prefix directory
1211+ # and they should be tar.gz files matching pytorch-*.tar.gz
1212+ if path .dirname (obj .key ) == prefix and obj .key .endswith (".tar.gz" ):
1213+ obj_names .append (obj .key )
1214+ return obj_names
1215+
1216+ # Original logic for whl and libtorch prefixes
11531217 for obj in BUCKET .objects .filter (Prefix = prefix ):
11541218 is_acceptable = any (
11551219 [path .dirname (obj .key ) == prefix ]
@@ -1331,6 +1395,7 @@ def main() -> None:
13311395 prefixes = PREFIXES if args .prefix == "all" else [args .prefix ]
13321396 for prefix in prefixes :
13331397 generate_pep503 = prefix .startswith ("whl" )
1398+ generate_source_code = prefix .startswith ("source_code" )
13341399 print (f"INFO: { action } for '{ prefix } '" )
13351400 stime = time .time ()
13361401 idx = S3Index .from_S3 (
@@ -1345,11 +1410,15 @@ def main() -> None:
13451410 elif args .do_not_upload :
13461411 if generate_pep503 :
13471412 idx .save_pep503_htmls ()
1413+ elif generate_source_code :
1414+ idx .save_source_code_html ()
13481415 else :
13491416 idx .save_libtorch_html ()
13501417 else :
13511418 if generate_pep503 :
13521419 idx .upload_pep503_htmls ()
1420+ elif generate_source_code :
1421+ idx .upload_source_code_html ()
13531422 else :
13541423 idx .upload_libtorch_html ()
13551424
0 commit comments