1919import argparse
2020import collections
2121import json
22+ import urllib .parse
2223from pathlib import Path
2324
24- def generate_manifest (directory , prefix , output_dir ):
25+ def _get_out_template_name (template_name ):
26+ return f"{ urllib .parse .quote (template_name )} .json"
27+
28+ def generate_manifest (template_mapping , prefix , output_dir ):
2529 # Code to generate the manifest file
26-
30+
2731 response_templates = []
2832 res = {
2933 "response_templates" : response_templates
3034 }
3135 try :
32- template_mapping = _get_template_mapping (directory )
3336 for template_name , template_list in sorted (template_mapping .items (), key = lambda x : x [0 ]):
34- out_template_name = f" { template_name } .json"
37+ out_template_name = _get_out_template_name ( template_name )
3538 curr_template_name = template_name
3639
3740 templates_version = []
@@ -54,7 +57,7 @@ def generate_manifest(directory, prefix, output_dir):
5457 "versions" : templates_version ,
5558 "link" : f"{ prefix } { out_template_name } "
5659 })
57-
60+
5861 with open (Path (output_dir ) / "manifest.json" , 'w' ) as out_file :
5962 out_file .write (json .dumps (res , indent = 2 ))
6063
@@ -67,54 +70,67 @@ def _get_template_mapping(directory):
6770 path = Path (directory )
6871 if not path .exists () or not path .is_dir ():
6972 raise ValueError (f"The directory { directory } does not exist or is not a directory." )
70-
73+
7174 # Check for non-JSON files
7275 non_json_files = [f .name for f in path .iterdir () if f .is_file () and f .suffix != '.json' ]
7376 if non_json_files :
7477 raise ValueError (f"Non-JSON files found in directory { directory } : { ', ' .join (non_json_files )} " )
75-
78+
7679 files = [f for f in path .glob ("*.json" ) if f .is_file ()]
7780 if not files :
7881 raise ValueError (f"No files found in the directory { directory } to merge." )
79-
82+
8083 template_to_file_mapping = collections .defaultdict (list )
8184
8285 for file in files :
83- name_split = file .stem .rsplit ("_v" , 1 )
84- if len (name_split ) != 2 :
85- raise ValueError (f"File { file .name } does not match expected pattern '<template_name>_v<version>'" )
86- template_name = name_split [0 ]
87- version = name_split [1 ]
88-
89- template_to_file_mapping [template_name ].append ((version , file ))
90-
86+ with open (file , 'r' ) as in_file :
87+ try :
88+ content = in_file .read ()
89+ template_json = json .loads (content )
90+ template_name = template_json .get ("name" )
91+ version = template_json .get ("version" )
92+ if not template_name or not version :
93+ raise ValueError (f"File { file .name } is missing required 'name' or 'version' fields in JSON content." )
94+ template_to_file_mapping [template_name ].append ((version , file ))
95+ except json .JSONDecodeError as e :
96+ raise ValueError (f"File { file .name } contains invalid JSON: { e } " )
97+
98+ # Validate that (template_name, version) pairs are unique
99+ for template_name , template_list in template_to_file_mapping .items ():
100+ seen_versions = {}
101+ for version , file in template_list :
102+ if version in seen_versions :
103+ raise ValueError (
104+ f"Duplicate version '{ version } ' for template '{ template_name } ': "
105+ f"found in both '{ seen_versions [version ].name } ' and '{ file .name } '"
106+ )
107+ seen_versions [version ] = file
108+
91109 # Sort each template's version list by version number (ascending order)
92110 for template_name in template_to_file_mapping :
93111 try :
94112 template_to_file_mapping [template_name ].sort (key = lambda x : int (x [0 ]))
95113 except ValueError :
96114 raise ValueError (f"Template '{ template_name } ' has invalid version(s) that cannot be converted to integer" )
97-
115+
98116 return template_to_file_mapping
99117
100- def merge_files (directory , output_dir ):
118+ def merge_files (template_mapping , output_dir ):
101119 try :
102- template_mapping = _get_template_mapping (directory )
103-
104120 for template_name , template_list in sorted (template_mapping .items (), key = lambda x : x [0 ]):
105- out_template_name = f" { template_name } .json"
121+ out_template_name = _get_out_template_name ( template_name )
106122
107123 templates = []
108124 for _ , file in template_list :
109125 with open (file , 'r' ) as in_file :
110126 content = in_file .read ()
111127 templates .append (json .loads (content ))
112-
128+
113129 with open (Path (output_dir ) / out_template_name , 'w' ) as out_file :
114130 out_file .write (json .dumps (templates , indent = 2 ))
115131 except Exception as e :
116132 print (f"Error during merging files: { e } " )
117- raise
133+ raise
118134
119135def main ():
120136 parser = argparse .ArgumentParser (description = "Response template file merger and manifest generator" )
@@ -128,11 +144,13 @@ def main():
128144
129145 output_path = Path (args .output )
130146 output_path .mkdir (parents = True , exist_ok = True )
131-
132- merge_files (args .directory , args .output )
147+
148+ template_mapping = _get_template_mapping (args .directory )
149+
150+ merge_files (template_mapping , args .output )
133151
134152 if args .manifest :
135- generate_manifest (args . directory , args .prefix , args .output )
153+ generate_manifest (template_mapping , args .prefix , args .output )
136154
137155if __name__ == "__main__" :
138156 main ()
0 commit comments