@@ -115,7 +115,83 @@ def process_console_output(res, target, action, run_args):
115115if default_parent is None :
116116 default_parent = Action ()
117117
118- # Main CLI function
118+
119+ log_flag_aliases = {'-v' : '--verbose' , '-s' : '--silent' }
120+ log_levels = {'--verbose' : logging .DEBUG , '--silent' : logging .WARNING }
121+
122+
123+ def build_pre_parser ():
124+ pre_parser = argparse .ArgumentParser (add_help = False )
125+ pre_parser .add_argument ("action" , nargs = "?" , help = "Top-level action (run, build, help, etc.)" )
126+ pre_parser .add_argument ("target" , choices = ['run' , 'script' , 'cache' , 'repo' ], nargs = "?" , help = "Target (repo, script, cache, ...)" )
127+ pre_parser .add_argument ("-h" , "--help" , action = "store_true" )
128+ return pre_parser
129+
130+
131+ def build_parser (pre_args ):
132+ parser = argparse .ArgumentParser (prog = "mlc" , description = "Manage repos, scripts, and caches." , add_help = False )
133+ subparsers = parser .add_subparsers (dest = "command" , required = not pre_args .help )
134+
135+ # General commands
136+ for action in ['run' , 'pull' , 'test' , 'add' , 'show' , 'list' , 'find' , 'search' , 'rm' , 'cp' , 'mv' , 'help' ]:
137+ p = subparsers .add_parser (action , add_help = False )
138+ p .add_argument ('target' , choices = ['repo' , 'script' , 'cache' ])
139+ p .add_argument ('details' , nargs = '?' , help = 'Details or identifier (optional)' )
140+ p .add_argument ('extra' , nargs = argparse .REMAINDER )
141+
142+ # Script-only
143+ for action in ['docker' , 'experiment' , 'doc' , 'lint' ]:
144+ p = subparsers .add_parser (action , add_help = False )
145+ p .add_argument ('target' , choices = ['script' , 'run' ])
146+ p .add_argument ('details' , nargs = '?' , help = 'Details or identifier (optional)' )
147+ p .add_argument ('extra' , nargs = argparse .REMAINDER )
148+
149+ # Load cfg
150+ load_parser = subparsers .add_parser ("load" , add_help = False )
151+ load_parser .add_argument ("target" , choices = ["cfg" ])
152+ return parser
153+
154+
155+ def configure_logging (args ):
156+ if hasattr (args , 'extra' ) and args .extra :
157+ args .extra [:] = [log_flag_aliases .get (a , a ) for a in args .extra ]
158+ for flag , level in log_levels .items ():
159+ if flag in args .extra :
160+ logging .getLogger ().setLevel (level )
161+ args .extra .remove (flag )
162+
163+
164+ def build_run_args (args ):
165+ res = utils .convert_args_to_dictionary (getattr (args , 'extra' , []))
166+ if res ['return' ] > 0 :
167+ return res
168+
169+ run_args = res ['args_dict' ]
170+ run_args ['mlc_run_cmd' ] = shlex .join (sys .argv )
171+
172+ if args .command in ['pull' , 'rm' , 'add' , 'find' ] and args .target == "repo" :
173+ run_args ['repo' ] = args .details
174+
175+ if args .command in ['docker' , 'experiment' , 'doc' , 'lint' ] and args .target == "run" :
176+ run_args ['target' ] = 'script'
177+ args .target = "script"
178+
179+ if args .details and not utils .is_uid (args .details ) and not run_args .get ("tags" ) and args .target in ["script" , "cache" ]:
180+ run_args ['tags' ] = args .details
181+
182+ if not run_args .get ('details' ) and args .details :
183+ run_args ['details' ] = args .details
184+
185+ if args .command in ["cp" , "mv" ]:
186+ run_args ['target' ] = args .target
187+ if args .details :
188+ run_args ['src' ] = args .details
189+ if args .extra :
190+ run_args ['dest' ] = args .extra [0 ]
191+
192+ return run_args
193+
194+
119195def main ():
120196 """
121197 MLCFlow is a CLI tool for managing repos, scripts, and caches.
@@ -154,15 +230,16 @@ def main():
154230 mlc run script --help
155231 mlc pull repo -h
156232 """
157-
158- # First level parser for showing help
159- pre_parser = argparse .ArgumentParser (add_help = False )
160- pre_parser .add_argument ("action" , nargs = "?" , help = "Top-level action (run, build, help, etc.)" )
161- pre_parser .add_argument ("target" , choices = ['run' , 'script' , 'cache' , 'repo' ], nargs = "?" , help = "Potential target (repo, script, cache, ...)" )
162- pre_parser .add_argument ("-h" , "--help" , action = "store_true" )
233+ pre_parser = build_pre_parser ()
163234 pre_args , remaining_args = pre_parser .parse_known_args ()
164235
165- if pre_args .help and not any ("--tags" in arg for arg in remaining_args ):
236+ parser = build_parser (pre_args )
237+ args = parser .parse_args () if remaining_args or pre_args .target else pre_args
238+
239+ configure_logging (args )
240+ run_args = build_run_args (args ) if hasattr (args , "command" ) else {}
241+
242+ if pre_args .help and not "tags" in run_args :
166243 help_text = ""
167244 if pre_args .target == "run" :
168245 if pre_args .action == "docker" :
@@ -196,104 +273,20 @@ def main():
196273 if help_text != "" :
197274 print (help_text )
198275 sys .exit (0 )
199-
200- # parser for execution of the automation scripts
201- parser = argparse .ArgumentParser (prog = 'mlc' , description = 'A CLI tool for managing repos, scripts, and caches.' , add_help = False )
202-
203- # Subparsers are added to main parser, allowing for different commands (subcommands) to be defined.
204- # The chosen subcommand will be stored in the "command" attribute of the parsed arguments.
205- subparsers = parser .add_subparsers (dest = 'command' , required = True )
206-
207- # Script and Cache-specific subcommands
208- for action in ['run' , 'pull' , 'test' , 'add' , 'show' , 'list' , 'find' , 'search' , 'rm' , 'cp' , 'mv' ]:
209- action_parser = subparsers .add_parser (action , add_help = False )
210- action_parser .add_argument ('target' , choices = ['repo' , 'script' , 'cache' ], help = 'Target type (repo, script, cache).' )
211- # the argument given after target and before any extra options like --tags will be stored in "details"
212- action_parser .add_argument ('details' , nargs = '?' , help = 'Details or identifier (optional for list).' )
213- action_parser .add_argument ('extra' , nargs = argparse .REMAINDER , help = 'Extra options (e.g., -v)' )
214-
215- # Script specific subcommands
216- for action in ['docker' , 'experiment' , 'doc' , 'lint' ]:
217- action_parser = subparsers .add_parser (action , add_help = False )
218- action_parser .add_argument ('target' , choices = ['script' , 'run' ], help = 'Target type (script).' )
219- # the argument given after target and before any extra options like --tags will be stored in "details"
220- action_parser .add_argument ('details' , nargs = '?' , help = 'Details or identifier (optional for list).' )
221- action_parser .add_argument ('extra' , nargs = argparse .REMAINDER , help = 'Extra options (e.g., -v)' )
222-
223- for action in ['load' ]:
224- load_parser = subparsers .add_parser (action , add_help = False )
225- load_parser .add_argument ('target' , choices = ['cfg' ], help = 'Target type (cfg).' )
226-
227- # Parse arguments
228- args = parser .parse_args ()
229276
230- #logger.info(f"Args = {args}")
231-
232- # set log level for MLCFlow if -v/--verbose or -s/--silent is specified
233- log_flag_aliases = {
234- '-v' : '--verbose' ,
235- '-s' : '--silent'
236- }
237-
238- log_levels = {
239- '--verbose' : logging .DEBUG ,
240- '--silent' : logging .WARNING
241- }
242-
243- # Modify args.extra in place
244- args .extra [:] = [log_flag_aliases .get (arg , arg ) for arg in args .extra ]
277+ action = get_action (args .target , default_parent )
245278
246- # Set log level based on the first matching flag
247- for flag , level in log_levels .items ():
248- if flag in args .extra :
249- logger .setLevel (level )
250- args .extra .remove (flag )
279+ if not action or not hasattr (action , args .command ):
280+ logging .error ("Error: '%s' is not supported for %s." , args .command , args .target )
281+ sys .exit (1 )
251282
252- res = utils .convert_args_to_dictionary (args .extra )
283+ method = getattr (action , args .command )
284+ res = method (run_args )
253285 if res ['return' ] > 0 :
254- return res
255-
256- run_args = res ['args_dict' ]
257-
258- run_args ['mlc_run_cmd' ] = " " .join (shlex .quote (arg ) for arg in sys .argv )
259-
260- if hasattr (args , 'repo' ) and args .repo :
261- run_args ['repo' ] = args .repo
262-
263- if args .command in ['pull' , 'rm' , 'add' , 'find' ]:
264- if args .target == "repo" :
265- run_args ['repo' ] = args .details
266-
267- if args .command in ['docker' , 'experiment' , 'doc' , 'lint' ]:
268- if args .target == "run" :
269- run_args ['target' ] = 'script' #allowing run to be used for docker run instead of docker script
270- args .target = "script"
271-
272- if hasattr (args , 'details' ) and args .details and not utils .is_uid (args .details ) and not run_args .get ("tags" ) and args .target in ["script" , "cache" ]:
273- run_args ['tags' ] = args .details
286+ logging .error (res .get ('error' , f"Error in { action } " ))
287+ raise Exception (f"An error occurred { res } " )
274288
275- if not run_args .get ('details' ) and args .details :
276- run_args ['details' ] = args .details
277-
278- if args .command in ["cp" , "mv" ]:
279- run_args ['target' ] = args .target
280- if hasattr (args , 'details' ) and args .details :
281- run_args ['src' ] = args .details
282- if hasattr (args , 'extra' ) and args .extra :
283- run_args ['dest' ] = args .extra [0 ]
284-
285- # Get the action handler for other commands
286- action = get_action (args .target , default_parent )
287- # Dynamically call the method (e.g., run, list, show)
288- if action and hasattr (action , args .command ):
289- method = getattr (action , args .command )
290- res = method (run_args )
291- if res ['return' ] > 0 :
292- logger .error (res .get ('error' , f"Error in { action } " ))
293- raise Exception (f"""An error occurred { res } """ )
294- process_console_output (res , args .target , args .command , run_args )
295- else :
296- logger .error (f"Error: '{ args .command } ' is not supported for { args .target } ." )
289+ process_console_output (res , args .target , args .command , run_args )
297290
298291if __name__ == '__main__' :
299292 main ()
0 commit comments