11import os
2+ import shlex
23import sys
34import argparse
4- import toml
5- import click
5+ from icortex .kernel import get_icortex_kernel
66from jupyter_console .app import ZMQTerminalIPythonApp
7- from icortex .services import service_dict , get_service
8- from icortex .config import DEFAULT_SERVICE , DEFAULT_ICORTEX_CONFIG_PATH
7+ from icortex .services import get_available_services
8+ from icortex .defaults import DEFAULT_ICORTEX_CONFIG_PATH
99from icortex .install import is_kernel_installed , main as install_kernel
10- from icortex .kernel import ICortexKernel
10+ from icortex .config import ICortexConfig
1111
1212# Jupyter devs did not make this easy
1313# TODO: Make less hacky
@@ -18,83 +18,197 @@ def parse_command_line(self, argv=None):
1818 self .build_kernel_argv (self .extra_args )
1919
2020
21- def initialize_config (path : str ):
22- sorted_services = sorted (
23- [key for key , val in service_dict .items () if not val .hidden ]
21+ def get_parser (prog = None ):
22+ service_names = get_available_services ()
23+ parser = argparse .ArgumentParser (add_help = False )
24+ if prog is not None :
25+ parser .prog = prog
26+
27+ subparsers = parser .add_subparsers (dest = "command" )
28+
29+ ######################
30+ # Initialize ICortex #
31+ ######################
32+
33+ # //init
34+ parser_init = subparsers .add_parser (
35+ "init" ,
36+ help = "Initialize ICortex configuration in the current directory" ,
37+ add_help = False ,
38+ )
39+
40+ parser_init .add_argument (
41+ "--force" , action = "store_true" , help = "Force overwrite an existing configuration"
2442 )
25- sorted_services .remove (DEFAULT_SERVICE )
26- sorted_services = [DEFAULT_SERVICE ] + sorted_services
2743
28- service_name = click .prompt (
29- "Which code generation service would you like to use?\n Options: "
30- + ", " .join (sorted_services )
31- + "\n Default" ,
44+ parser_init .add_argument (
45+ "--config" ,
3246 type = str ,
33- default = DEFAULT_SERVICE ,
47+ help = "Path to the configuration TOML file." ,
48+ default = DEFAULT_ICORTEX_CONFIG_PATH ,
3449 )
3550
36- try :
37- service = get_service (service_name )
38- except KeyError :
39- print (f"Service does not exist: { service_name } " )
40- quit ()
51+ ##########################
52+ # Shell related commands #
53+ ##########################
4154
42- print (f"Selected service: { service_name } " )
43- skip_defaults = click .confirm ("Use default options?" , default = True )
44- service_config = service .config_dialog (service , skip_defaults = skip_defaults )
55+ # //shell
56+ parser_shell = subparsers .add_parser (
57+ "shell" ,
58+ help = "Start ICortex shell" ,
59+ add_help = False ,
60+ )
4561
46- toml_dict = { "service" : service_name , service_name : {}}
47- for key , val in service_config . items ():
48- toml_dict [ service_name ][ key ] = val
62+ ########
63+ # Help #
64+ ########
4965
50- with open (path , "w" ) as f :
51- toml .dump (toml_dict , f )
66+ # //help
67+ parser_help = subparsers .add_parser (
68+ "help" ,
69+ help = "Print help" ,
70+ add_help = False ,
71+ )
5272
73+ ############################
74+ # Service related commands #
75+ ############################
5376
54- def get_parser ():
55- parser = argparse .ArgumentParser ()
77+ # //service
78+ parser_service = subparsers .add_parser (
79+ "service" ,
80+ help = "Set and configure code generation services" ,
81+ add_help = False ,
82+ )
83+ parser_service_commands = parser_service .add_subparsers (
84+ dest = "service_command" ,
85+ required = True ,
86+ )
5687
57- parser . add_argument (
58- "-i" ,
59- "--init " ,
60- action = "store_true " ,
61- help = "Initialize ICortex configuration file in the current directory" ,
88+ # //service set <service_name>
89+ parser_service_commands_set = parser_service_commands . add_parser (
90+ "set " ,
91+ help = "Set the service to be used for code generation " ,
92+ add_help = False ,
6293 )
63- parser .add_argument (
64- "-c" ,
65- "--config" ,
94+ parser_service_commands_set .add_argument (
95+ "service_name" ,
96+ choices = service_names ,
97+ help = "Name of the service to be used for code generation" ,
98+ )
99+
100+ # //service show <service_name>
101+ parser_service_commands_show = parser_service_commands .add_parser (
102+ "show" ,
103+ help = "Show current service" ,
104+ add_help = False ,
105+ )
106+
107+ # //service help
108+ parser_service_commands_help = parser_service_commands .add_parser (
109+ "help" ,
110+ help = "Print help for //service" ,
111+ add_help = False ,
112+ )
113+
114+ # //service set-var <variable_name> <variable_value>
115+ parser_service_commands_set_var = parser_service_commands .add_parser (
116+ "set-var" ,
117+ help = "Set a variable for the current service" ,
118+ add_help = False ,
119+ )
120+ parser_service_commands_set_var .add_argument (
121+ "variable_name" ,
122+ help = "Name of the variable to be changed" ,
123+ )
124+ parser_service_commands_set_var .add_argument (
125+ "variable_value" ,
66126 type = str ,
67- help = "Path to the configuration TOML file." ,
68- default = DEFAULT_ICORTEX_CONFIG_PATH ,
127+ help = "New value for the variable" ,
128+ )
129+
130+ # //service init <service_name>
131+ # Used to re-spawn the config dialog if some config for the service
132+ # already exists
133+ parser_service_commands_init = parser_service_commands .add_parser (
134+ "init" ,
135+ help = "Initialize the configuration for the given service" ,
136+ add_help = False ,
137+ )
138+ parser_service_commands_init .add_argument (
139+ "service_name" ,
140+ choices = service_names ,
141+ help = "Name of the service to be used for code generation" ,
69142 )
70- return parser
143+ if prog is not None :
144+ parser_init .prog = prog
145+ for action in parser ._actions :
146+ if isinstance (action , argparse ._SubParsersAction ):
147+ for _ , subparser in action .choices .items ():
148+ subparser .prog = prog
71149
150+ return parser , parser_service
72151
73- def read_config (path ):
74- return toml .load (open (path , "r" ))
75152
153+ def set_icortex_service (config_path = DEFAULT_ICORTEX_CONFIG_PATH ):
154+ kernel = get_icortex_kernel ()
155+ if kernel is not None :
156+ return ICortexConfig (DEFAULT_ICORTEX_CONFIG_PATH ).set_service ()
157+ return False
76158
77- def main (argv = None ):
159+
160+ def main (argv = None , prog = None ):
78161 if argv is None :
79162 argv = sys .argv [1 :]
80163
81- parser = get_parser ()
164+ parser , parser_service = get_parser (prog = prog )
82165 args = parser .parse_args (argv )
83166
84167 # Install kernel if it's not already
85168 if not is_kernel_installed ():
86169 install_kernel ()
87170
88- # If no config file exists, initialize it
89- if args .init or not os .path .exists (args .config ):
90- initialize_config (args .config )
91- # if args.init or not os.path.exists(DEFAULT_ICORTEX_CONFIG_PATH):
92- # initialize_config(DEFAULT_ICORTEX_CONFIG_PATH)
93-
94- # print(ICortexKernel.config_path)
95- # Launch shell
96- if not args .init :
97- ZMQTerminalICortexApp .launch_instance ()
171+ if "config" in args :
172+ config_path = args .config
173+ else :
174+ config_path = DEFAULT_ICORTEX_CONFIG_PATH
175+
176+ config = ICortexConfig (config_path )
177+
178+ if args .command == "init" :
179+ # If no config file exists, initialize it
180+ if os .path .exists (config_path ) and not args .force :
181+ print (f"The file { config_path } already exists. Use --force to overwrite." )
182+ else :
183+ config .init_config ()
184+ elif args .command == "service" :
185+ if args .service_command == "set" :
186+ config .set_service_config (args .service_name )
187+ elif args .service_command == "set-var" :
188+ config .set_service_var (args .variable_name , args .variable_value )
189+ elif args .service_command == "show" :
190+ print (config .format_current_service ())
191+ elif args .service_command == "init" :
192+ config .set_service_config (args .service_name , hard_init = True )
193+ elif args .service_command == "help" :
194+ parser_service .print_help ()
195+ elif args .command == "help" :
196+ parser .print_help ()
197+ elif args .command == "shell" or args .command is None :
198+ kernel = get_icortex_kernel ()
199+ if kernel is None :
200+ ZMQTerminalICortexApp .launch_instance ()
201+ else :
202+ # print("The ICortex shell is already running, skipping.")
203+ parser .print_help ()
204+
205+
206+ def eval_cli (prompt : str ):
207+ argv = shlex .split (prompt )
208+ try :
209+ return main (argv = argv , prog = "//" )
210+ except SystemExit :
211+ return
98212
99213
100214if __name__ == "__main__" :
0 commit comments