55import logging
66import json
77
8- def run_specialization_script (template_script_path , output_dir , edge_params_list , python_exe , copy_script_path ):
8+ def _normalize_output_relpath (template_script_path , output_relpath = None ):
9+ if output_relpath :
10+ relpath = output_relpath .replace ("\\ " , "/" ).lstrip ("/" )
11+ else :
12+ relpath = os .path .basename (template_script_path )
13+ if not relpath :
14+ raise ValueError ("Output relative path cannot be empty." )
15+ return relpath
16+
17+
18+ def _join_output_path (output_dir , output_relpath ):
19+ return os .path .join (output_dir , * output_relpath .split ("/" ))
20+
21+
22+ def run_specialization_script (
23+ template_script_path ,
24+ output_dir ,
25+ edge_params_list ,
26+ python_exe ,
27+ copy_script_path ,
28+ output_relpath = None
29+ ):
930 """
1031 Calls the copy script to generate a specialized version of a node's script.
1132 Returns the basename of the generated script on success, None on failure.
1233 """
13- # The new copy script generates a standardized filename, e.g., "original.py"
1434 base_template_name = os .path .basename (template_script_path )
15- template_root , template_ext = os .path .splitext (base_template_name )
16- output_filename = f"{ template_root } { template_ext } "
17- expected_output_path = os .path .join (output_dir , output_filename )
35+ output_relpath = _normalize_output_relpath (template_script_path , output_relpath )
36+ expected_output_path = _join_output_path (output_dir , output_relpath )
1837
1938 # If the specialized file already exists, we don't need to regenerate it.
2039 if os .path .exists (expected_output_path ):
2140 logging .info (f"Specialized script '{ expected_output_path } ' already exists. Using existing." )
22- return output_filename
41+ return output_relpath
2342
2443 # Convert the list of parameters to a JSON string for command line argument
2544 edge_params_json_str = json .dumps (edge_params_list )
@@ -31,13 +50,15 @@ def run_specialization_script(template_script_path, output_dir, edge_params_list
3150 output_dir ,
3251 edge_params_json_str # Pass the JSON string as the last argument
3352 ]
53+ if output_relpath :
54+ cmd .append (output_relpath )
3455 logging .info (f"Running specialization for '{ base_template_name } ': { ' ' .join (cmd )} " )
3556 try :
3657 result = subprocess .run (cmd , capture_output = True , text = True , check = True , encoding = 'utf-8' )
37- logging .info (f"Successfully generated specialized script '{ output_filename } '." )
58+ logging .info (f"Successfully generated specialized script '{ output_relpath } '." )
3859 if result .stdout : logging .debug (f"copy_with_port_portname.py stdout:\n { result .stdout .strip ()} " )
3960 if result .stderr : logging .warning (f"copy_with_port_portname.py stderr:\n { result .stderr .strip ()} " )
40- return output_filename
61+ return output_relpath
4162 except subprocess .CalledProcessError as e :
4263 logging .error (f"Error calling specialization script for '{ template_script_path } ':" )
4364 logging .error (f"Command: { ' ' .join (e .cmd )} " )
@@ -50,7 +71,7 @@ def run_specialization_script(template_script_path, output_dir, edge_params_list
5071 return None
5172
5273
53- def create_modified_script (template_script_path , output_dir , edge_params_json_str ):
74+ def create_modified_script (template_script_path , output_dir , edge_params_json_str , output_relpath = None ):
5475 """
5576 Creates a modified Python script by injecting ZMQ port and port name
5677 definitions from a JSON object.
@@ -121,17 +142,16 @@ def create_modified_script(template_script_path, output_dir, edge_params_json_st
121142 modified_lines = lines [:insert_index ] + definitions + lines [insert_index :]
122143
123144 # --- Determine and create output file ---
124- base_template_name = os .path .basename (template_script_path )
125- template_root , template_ext = os .path .splitext (base_template_name )
126-
127- # Standardized output filename for a node with one or more specializations
128- output_filename = f"{ template_root } { template_ext } "
129- output_script_path = os .path .join (output_dir , output_filename )
145+ output_relpath = _normalize_output_relpath (template_script_path , output_relpath )
146+ output_script_path = _join_output_path (output_dir , output_relpath )
130147
131148 try :
132149 if not os .path .exists (output_dir ):
133150 os .makedirs (output_dir )
134151 print (f"Created output directory: { output_dir } " )
152+ output_parent = os .path .dirname (output_script_path )
153+ if output_parent and not os .path .exists (output_parent ):
154+ os .makedirs (output_parent , exist_ok = True )
135155
136156 with open (output_script_path , 'w' ) as f :
137157 f .writelines (modified_lines )
@@ -149,14 +169,15 @@ def create_modified_script(template_script_path, output_dir, edge_params_json_st
149169 datefmt = '%Y-%m-%d %H:%M:%S'
150170 )
151171
152- if len (sys .argv ) != 4 :
153- print ("\n Usage: python3 copy_with_port_portname.py <TEMPLATE_SCRIPT_PATH> <OUTPUT_DIRECTORY> '<JSON_PARAMETERS>'\n " )
172+ if len (sys .argv ) not in [ 4 , 5 ] :
173+ print ("\n Usage: python3 copy_with_port_portname.py <TEMPLATE_SCRIPT_PATH> <OUTPUT_DIRECTORY> '<JSON_PARAMETERS>' [OUTPUT_RELATIVE_PATH] \n " )
154174 print ("Example JSON: '[{\" port\" : \" 2355\" , \" port_name\" : \" FUNBODY_REP_1\" , \" source_node_label\" : \" nodeA\" , \" target_node_label\" : \" nodeB\" }]'" )
155175 print ("Note: The JSON string must be enclosed in single quotes in shell.\n " )
156176 sys .exit (1 )
157177
158178 template_script_path_arg = sys .argv [1 ]
159179 output_directory_arg = sys .argv [2 ]
160180 json_params_arg = sys .argv [3 ]
181+ output_relpath_arg = sys .argv [4 ] if len (sys .argv ) == 5 else None
161182
162- create_modified_script (template_script_path_arg , output_directory_arg , json_params_arg )
183+ create_modified_script (template_script_path_arg , output_directory_arg , json_params_arg , output_relpath_arg )
0 commit comments