3030from ducktools .lazyimporter import LazyImporter , FromImport
3131
3232from ducktools .env import __version__ , PROJECT_NAME
33+ from ducktools .env .exceptions import EnvError
3334
3435_laz = LazyImporter (
3536 [
@@ -191,7 +192,7 @@ def get_parser(prog, exit_on_error=True) -> FixedArgumentParser:
191192 create_zipapp_parser .add_argument (
192193 "--zipapp" ,
193194 action = "store_true" ,
194- help = "Also create the portable ducktools.pyz zipapp" ,
195+ help = "Also create the portable ducktools-env .pyz zipapp" ,
195196 )
196197
197198 list_parser = subparsers .add_parser (
@@ -284,9 +285,159 @@ def get_columns(
284285 )
285286
286287
287- def main ():
288- if __name__ == "__main__" :
289- command = f"{ os .path .basename (sys .executable )} -m ducktools.env"
288+ def run_command (manager , args ):
289+ # Split on existence of the command as a file, if the file exists run it
290+ # Otherwise look for it in the registered scripts database
291+
292+ if os .path .isfile (args .script_filename ):
293+ returncode = manager .run_script (
294+ script_path = args .script_filename ,
295+ script_args = args .script_args ,
296+ generate_lock = args .generate_lock ,
297+ lock_path = args .with_lock ,
298+ )
299+ else :
300+ returncode = manager .run_registered_script (
301+ script_name = args .script_filename ,
302+ script_args = args .script_args ,
303+ generate_lock = args .generate_lock ,
304+ lock_path = args .with_lock ,
305+ )
306+
307+ return returncode
308+
309+
310+ def bundle_command (manager , args ):
311+ manager .create_bundle (
312+ script_path = args .script_filename ,
313+ with_lock = args .with_lock ,
314+ generate_lock = args .generate_lock ,
315+ output_file = args .output ,
316+ compressed = args .compress ,
317+ )
318+
319+ return 0
320+
321+
322+ def register_command (manager , args ):
323+ if args .remove :
324+ # filename should just be the script name, but it's awkward to change this
325+ manager .remove_registered_script (
326+ script_name = args .script_filename ,
327+ )
328+ else :
329+ manager .register_script (
330+ script_path = args .script_filename ,
331+ script_name = args .name ,
332+ )
333+
334+ return 0
335+
336+
337+ def generate_lock_command (manager , args ):
338+ lock_path = manager .generate_lockfile (
339+ script_path = args .script_filename ,
340+ lockfile_path = args .output ,
341+ )
342+ print (f"Lockfile generated at '{ lock_path } '" )
343+
344+ return 0
345+
346+
347+ def clear_cache_command (manager , args ):
348+ if args .full :
349+ manager .clear_project_folder ()
350+ else :
351+ manager .clear_temporary_cache ()
352+
353+ return 0
354+
355+
356+ def rebuild_env_command (manager , args ):
357+ manager .build_env_folder ()
358+ if args .zipapp :
359+ manager .build_zipapp ()
360+
361+ return 0
362+
363+
364+ def list_command (manager , args ):
365+ has_data = False
366+ show_temp = args .temp or not (args .app or args .scripts )
367+ show_app = args .app or not (args .scripts or args .temp )
368+ show_scripts = args .scripts or not (args .app or args .temp )
369+
370+ if (envs := manager .temp_catalogue .environments ) and show_temp :
371+ has_data = True
372+ print ("Temporary Environments" )
373+ print ("======================" )
374+ formatted = get_columns (
375+ data = envs .values (),
376+ headings = ["Name" , "Last Used" ],
377+ attributes = ["name" , "last_used_simple" ],
378+ )
379+ for line in formatted :
380+ print (line )
381+ if not args .temp :
382+ # newline if not exclusive
383+ print ()
384+
385+ if (envs := manager .app_catalogue .environments ) and show_app :
386+ has_data = True
387+ print ("Application Environments" )
388+ print ("========================" )
389+ formatted = get_columns (
390+ data = envs .values (),
391+ headings = ["Owner / Name" , "Last Used" ],
392+ attributes = ["name" , "last_used_simple" ],
393+ )
394+ for line in formatted :
395+ print (line )
396+ if not args .app :
397+ # newline if not exclusive
398+ print ()
399+
400+ if (scripts := manager .script_registry .list_registered_scripts ()) and show_scripts :
401+ has_data = True
402+ print ("Registered Scripts" )
403+ print ("==================" )
404+
405+ formatted = get_columns (
406+ data = scripts ,
407+ headings = ["Script Name" , "Path" ],
408+ attributes = ["name" , "path" ],
409+ )
410+ for line in formatted :
411+ print (line )
412+ print ()
413+
414+ if has_data is False :
415+ print ("No environments or scripts managed by ducktools-env" )
416+
417+ return 0
418+
419+
420+ def delete_env_command (manager , args ):
421+ envname = args .environment_name
422+ if envname in manager .temp_catalogue .environments :
423+ manager .temp_catalogue .delete_env (envname )
424+ print (f"Temporary environment { envname !r} deleted" )
425+ elif envname in manager .app_catalogue .environments :
426+ manager .app_catalogue .delete_env (envname )
427+ print (f"Application environment { envname !r} deleted" )
428+ else :
429+ print (f"Environment { envname !r} not found" )
430+
431+ return 0
432+
433+
434+ def main_command () -> int :
435+ executable_name = os .path .splitext (os .path .basename (sys .executable ))[0 ]
436+
437+ if zipapp_path := globals ().get ("zipapp_path" ):
438+ command = f"{ executable_name } { zipapp_path } "
439+ elif __name__ == "__main__" :
440+ command = f"{ executable_name } -m ducktools.env"
290441 else :
291442 command = os .path .basename (sys .argv [0 ])
292443
@@ -313,138 +464,37 @@ def main():
313464 command = command ,
314465 )
315466
316- if args .command == "run" :
317- # Split on existence of the command as a file, if the file exists run it
318- # Otherwise look for it in the registered scripts database
319- if os .path .isfile (args .script_filename ):
320- manager .run_script (
321- script_path = args .script_filename ,
322- script_args = args .script_args ,
323- generate_lock = args .generate_lock ,
324- lock_path = args .with_lock ,
325- )
326- else :
327- manager .run_registered_script (
328- script_name = args .script_filename ,
329- script_args = args .script_args ,
330- generate_lock = args .generate_lock ,
331- lock_path = args .with_lock ,
332- )
333-
334- elif args .command == "bundle" :
335- manager .create_bundle (
336- script_path = args .script_filename ,
337- with_lock = args .with_lock ,
338- generate_lock = args .generate_lock ,
339- output_file = args .output ,
340- compressed = args .compress ,
341- )
342-
343- elif args .command == "register" :
344- if args .remove :
345- # filename should just be the script name, but it's awkward to change this
346- manager .remove_registered_script (
347- script_name = args .script_filename ,
348- )
349- else :
350- manager .register_script (
351- script_path = args .script_filename ,
352- script_name = args .name ,
353- )
354-
355- elif args .command == "generate_lock" :
356- lock_path = manager .generate_lockfile (
357- script_path = args .script_filename ,
358- lockfile_path = args .output ,
359- )
360- print (f"Lockfile generated at '{ lock_path } '" )
361-
362- elif args .command == "clear_cache" :
363- if args .full :
364- manager .clear_project_folder ()
365- else :
366- manager .clear_temporary_cache ()
367-
368- elif args .command == "rebuild_env" :
369- manager .build_env_folder ()
370- if args .zipapp :
371- manager .build_zipapp ()
372-
373- elif args .command == "list" :
374- has_data = False
375- show_temp = args .temp or not (args .app or args .scripts )
376- show_app = args .app or not (args .scripts or args .temp )
377- show_scripts = args .scripts or not (args .app or args .temp )
378-
379- if (envs := manager .temp_catalogue .environments ) and show_temp :
380- has_data = True
381- print ("Temporary Environments" )
382- print ("======================" )
383- formatted = get_columns (
384- data = envs .values (),
385- headings = ["Name" , "Last Used" ],
386- attributes = ["name" , "last_used_simple" ],
387- )
388- for line in formatted :
389- print (line )
390- if not args .temp :
391- # newline if not exclusive
392- print ()
393-
394- if (envs := manager .app_catalogue .environments ) and show_app :
395- has_data = True
396- print ("Application Environments" )
397- print ("========================" )
398- formatted = get_columns (
399- data = envs .values (),
400- headings = ["Owner / Name" , "Last Used" ],
401- attributes = ["name" , "last_used_simple" ],
402- )
403- for line in formatted :
404- print (line )
405- if not args .app :
406- # newline if not exclusive
407- print ()
408-
409- if (scripts := manager .script_registry .list_registered_scripts ()) and show_scripts :
410- has_data = True
411- print ("Registered Scripts" )
412- print ("==================" )
413-
414- formatted = get_columns (
415- data = scripts ,
416- headings = ["Script Name" , "Path" ],
417- attributes = ["name" , "path" ],
418- )
419- for line in formatted :
420- print (line )
421- print ()
422-
423- if has_data is False :
424- print ("No environments or scripts managed by ducktools-env" )
425-
426- elif args .command == "delete_env" :
427- envname = args .environment_name
428- if envname in manager .temp_catalogue .environments :
429- manager .temp_catalogue .delete_env (envname )
430- print (f"Temporary environment { envname !r} deleted" )
431- elif envname in manager .app_catalogue .environments :
432- manager .app_catalogue .delete_env (envname )
433- print (f"Application environment { envname !r} deleted" )
434- else :
435- print (f"Environment { envname !r} not found" )
436- else :
437- # Should be unreachable
438- raise ValueError ("Invalid command" )
439-
440-
441- if __name__ == "__main__" :
467+ match args .command :
468+ case "run" :
469+ return run_command (manager , args )
470+ case "bundle" :
471+ return bundle_command (manager , args )
472+ case "register" :
473+ return register_command (manager , args )
474+ case "generate_lock" :
475+ return generate_lock_command (manager , args )
476+ case "clear_cache" :
477+ return clear_cache_command (manager , args )
478+ case "rebuild_env" :
479+ return rebuild_env_command (manager , args )
480+ case "list" :
481+ return list_command (manager , args )
482+ case "delete_env" :
483+ return delete_env_command (manager , args )
484+ case _:
485+ raise RuntimeError (f"Invalid Command { args .command !r} " )
486+
487+
488+ def main () -> int :
442489 try :
443- main ()
444- except RuntimeError as e :
490+ result = main_command ()
491+ except ( RuntimeError , EnvError ) as e :
445492 errors = "\n " .join (e .args ) + "\n "
446493 if sys .stderr :
447494 sys .stderr .write (errors )
448- sys .exit (1 )
495+ return 1
496+ return 0
449497
450- sys .exit (0 )
498+
499+ if __name__ == "__main__" :
500+ sys .exit (main ())
0 commit comments