1616import  time 
1717from  datetime  import  datetime 
1818from  pathlib  import  Path 
19- from  typing  import  Any , Dict , List , Optional 
19+ from  typing  import  Any , Dict , List , Optional ,  Tuple 
2020import  click 
2121from  lean .click  import  LeanCommand , PathParameter , ensure_options 
2222from  lean .constants  import  DEFAULT_ENGINE_IMAGE 
2323from  lean .container  import  container 
2424from  lean .models .brokerages .local  import  all_local_brokerages , local_brokerage_data_feeds , all_local_data_feeds 
2525from  lean .models .errors  import  MoreInfoError 
26+ from  lean .models .lean_config_configurer  import  LeanConfigConfigurer 
2627from  lean .models .logger  import  Option 
27- from  lean .models .configuration  import  Configuration , InfoConfiguration , InternalInputUserInput 
28+ from  lean .models .configuration  import  Configuration , InfoConfiguration , InternalInputUserInput ,  OrganzationIdConfiguration 
2829from  lean .models .click_options  import  options_from_json 
2930from  lean .models .json_module  import  JsonModule 
3031from  lean .commands .live .live  import  live 
3839    "real-time-handler" : "QuantConnect.Lean.Engine.RealTime.LiveTradingRealTimeHandler" 
3940}
4041
41- def  _raise_for_missing_properties (lean_config : Dict [str , Any ], environment_name : str , lean_config_path : Path ) ->  None :
42-     """Raises an error if any required properties are missing. 
42+ 
43+ def  _get_configurable_modules_from_environment (lean_config : Dict [str , Any ], environment_name : str ) ->  Tuple [LeanConfigConfigurer , List [LeanConfigConfigurer ]]:
44+     """Returns the configurable modules from the given environment. 
4345
4446    :param lean_config: the LEAN configuration that should be used 
4547    :param environment_name: the name of the environment 
46-     :param lean_config_path : the path to  the LEAN configuration file  
48+     :return : the configurable modules from  the given environment  
4749    """ 
4850    environment  =  lean_config ["environments" ][environment_name ]
4951    for  key  in  ["live-mode-brokerage" , "data-queue-handler" ]:
@@ -53,9 +55,34 @@ def _raise_for_missing_properties(lean_config: Dict[str, Any], environment_name:
5355
5456    brokerage  =  environment ["live-mode-brokerage" ]
5557    data_queue_handlers  =  environment ["data-queue-handler" ]
56- 
5758    [brokerage_configurer ] =  [local_brokerage  for  local_brokerage  in  all_local_brokerages  if  local_brokerage .get_live_name (environment_name ) ==  brokerage ]
5859    data_feed_configurers  =  [local_data_feed  for  local_data_feed  in  all_local_data_feeds  if  local_data_feed .get_live_name (environment_name ) in  data_queue_handlers ]
60+     return  brokerage_configurer , data_feed_configurers 
61+ 
62+ 
63+ def  _install_modules (modules : List [LeanConfigConfigurer ], user_kwargs : Dict [str , Any ]) ->  None :
64+     """Raises an error if any of the given modules are not installed. 
65+ 
66+     :param modules: the modules to check 
67+     """ 
68+     for  module  in  modules :
69+         if  not  module ._installs :
70+             continue 
71+         organization_id  =  module .get_organzation_id ()
72+         if  organization_id  is  None  or  organization_id  ==  "" :
73+             [organization_config ] =  module .get_config_from_type (OrganzationIdConfiguration )
74+             organization_id  =  _get_non_interactive_organization_id (module , organization_config , user_kwargs )
75+         module .ensure_module_installed (organization_id )
76+ 
77+ 
78+ def  _raise_for_missing_properties (lean_config : Dict [str , Any ], environment_name : str , lean_config_path : Path ) ->  None :
79+     """Raises an error if any required properties are missing. 
80+ 
81+     :param lean_config: the LEAN configuration that should be used 
82+     :param environment_name: the name of the environment 
83+     :param lean_config_path: the path to the LEAN configuration file 
84+     """ 
85+     brokerage_configurer , data_feed_configurers  =  _get_configurable_modules_from_environment (lean_config , environment_name )
5986    brokerage_properties  =  brokerage_configurer .get_required_properties ()
6087    data_queue_handler_properties  =  []
6188    for  data_feed_configurer  in  data_feed_configurers :
@@ -136,7 +163,7 @@ def _configure_lean_config_interactively(lean_config: Dict[str, Any], environmen
136163            essential_properties_value  =  {config ._id  : config ._value  for  config  in  brokerage .get_essential_configs ()}
137164            data_feed .update_configs (essential_properties_value )
138165            container .logger ().debug (f"interactive: essential_properties_value: { brokerage ._id } { essential_properties_value }  )
139-             # now required properties can be fetched as per data/filter provider from esssential  properties 
166+             # now required properties can be fetched as per data/filter provider from essential  properties 
140167            required_properties_value  =  {config ._id  : config ._value  for  config  in  brokerage .get_required_configs ([InternalInputUserInput ])}
141168            data_feed .update_configs (required_properties_value )
142169            container .logger ().debug (f"interactive: required_properties_value: { required_properties_value }  )
@@ -178,6 +205,10 @@ def _get_organization_id(given_input: Optional[str], label: str) -> str:
178205    container .logger ().debug (f"deploy._get_organization_id: user selected organization id: { organization .id }  )
179206    return  organization .id 
180207
208+ def  _get_non_interactive_organization_id (module : LeanConfigConfigurer , 
209+                                         organization_config : OrganzationIdConfiguration , user_kwargs : Dict [str , Any ]) ->  str :
210+     return  _get_organization_id (user_kwargs [module ._convert_lean_key_to_variable (organization_config ._id )], module ._id )
211+ 
181212def  _get_and_build_module (target_module_name : str , module_list : List [JsonModule ], properties : Dict [str , Any ]):
182213    [target_module ] =  [module  for  module  in  module_list  if  module .get_name () ==  target_module_name ]
183214    # update essential properties from brokerage to datafeed 
@@ -187,12 +218,12 @@ def _get_and_build_module(target_module_name: str, module_list: List[JsonModule]
187218    essential_properties_value  =  {target_module ._convert_variable_to_lean_key (prop ) : properties [prop ] for  prop  in  essential_properties }
188219    target_module .update_configs (essential_properties_value )
189220    container .logger ().debug (f"non-interactive: essential_properties_value with module { target_module_name } { essential_properties_value }  )
190-     # now required properties can be fetched as per data/filter provider from esssential  properties 
221+     # now required properties can be fetched as per data/filter provider from essential  properties 
191222    required_properties : List [str ] =  []
192223    organization_info : Dict [str ,str ] =  {}
193224    for  config  in  target_module .get_required_configs ([InternalInputUserInput ]):
194225        if  config .is_type_organization_id :
195-             organization_info [config ._id ] =  _get_organization_id ( properties [ target_module . _convert_lean_key_to_variable ( config . _id )],  target_module . _id )
226+             organization_info [config ._id ] =  _get_non_interactive_organization_id ( target_module ,  config ,  properties )
196227            properties [target_module ._convert_lean_key_to_variable (config ._id )] =  organization_info [config ._id ]
197228            # skip organization id from ensure_options() because it is fetched using _get_organization_id() 
198229            continue 
@@ -362,6 +393,9 @@ def deploy(project: Path,
362393        raise  MoreInfoError (f"The '{ environment_name }  ,
363394                            "https://www.lean.io/docs/lean-cli/live-trading" )
364395
396+     env_brokerage , env_data_queue_handlers  =  _get_configurable_modules_from_environment (lean_config , environment_name )
397+     _install_modules ([env_brokerage ] +  env_data_queue_handlers , kwargs )
398+ 
365399    _raise_for_missing_properties (lean_config , environment_name , lean_config_manager .get_lean_config_path ())
366400
367401    project_config_manager  =  container .project_config_manager ()
0 commit comments