1- # Copyright 2020-2024 The MathWorks, Inc.
1+ # Copyright 2020-2025 The MathWorks, Inc.
22
33import datetime
44import os
@@ -47,7 +47,7 @@ def get_process_startup_timeout():
4747 return int (custom_startup_timeout )
4848
4949 else :
50- logger .warn (
50+ logger .warning (
5151 f"The value set for { mwi_env .get_env_name_process_startup_timeout ()} :{ custom_startup_timeout } is not a number. Using { constants .DEFAULT_PROCESS_START_TIMEOUT } as the default value"
5252 )
5353 return constants .DEFAULT_PROCESS_START_TIMEOUT
@@ -74,7 +74,7 @@ def get_matlab_executable_and_root_path():
7474 matlab_root_path = Path (custom_matlab_root_path )
7575
7676 # Terminate process if invalid Custom Path was provided!
77- mwi .validators .validate_matlab_root_path (
77+ matlab_root_path = mwi .validators .validate_matlab_root_path (
7878 matlab_root_path , is_custom_matlab_root = True
7979 )
8080
@@ -101,10 +101,9 @@ def get_matlab_executable_and_root_path():
101101
102102 # Control only gets here if custom matlab root was not set AND which matlab returned no results.
103103 # Note, error messages are formatted as multi-line strings and the front end displays them as is.
104- error_message = "Unable to find MATLAB on the system PATH. Add MATLAB to the system PATH, and restart matlab-proxy."
105-
106- logger .error (error_message )
107- raise MatlabInstallError (error_message )
104+ raise MatlabInstallError (
105+ "Unable to find MATLAB on the system PATH. Add MATLAB to the system PATH, and restart matlab-proxy."
106+ )
108107
109108
110109def get_matlab_version (matlab_root_path ):
@@ -126,7 +125,16 @@ def get_matlab_version(matlab_root_path):
126125 tree = ET .parse (version_info_file_path )
127126 root = tree .getroot ()
128127
129- return root .find ("release" ).text
128+ matlab_version = root .find ("release" ).text
129+
130+ # If the matlab on system PATH is a wrapper script, then it would not be possible to determine MATLAB root (inturn not being able to determine MATLAB version)
131+ # unless MWI_CUSTOM_MATLAB_ROOT is set. Raising only a warning as the matlab version is only required for communicating with MHLM.
132+ if not matlab_version :
133+ logger .warning (
134+ f"Could not determine MATLAB version from MATLAB root path: { matlab_root_path } . Set { mwi_env .get_env_name_custom_matlab_root ()} to a valid MATLAB root path"
135+ )
136+
137+ return matlab_version
130138
131139
132140def get_ws_env_settings ():
@@ -270,15 +278,7 @@ def get(config_name=matlab_proxy.get_default_config_name(), dev=False):
270278 logger .warning (warning )
271279 settings ["warnings" ].append (warning )
272280
273- try :
274- # Update settings with matlab specific values.
275- settings .update (get_matlab_settings ())
276- except UIVisibleFatalError as error :
277- logger .error (f"Exception raised during initialization: { error } " )
278- settings ["error" ] = error
279- # Exceptions of this kind must propagate to the UI.
280- # Returning settings that have been created without exceptions
281- pass
281+ settings .update (get_matlab_settings ())
282282
283283 return settings
284284
@@ -362,84 +362,33 @@ def get_matlab_settings():
362362 Unless they are of type UIVisibleFatalError
363363 """
364364
365- matlab_executable_path , matlab_root_path = get_matlab_executable_and_root_path ()
366-
367365 ws_env , ws_env_suffix = get_ws_env_settings ()
366+ mw_licensing_urls = _get_mw_licensing_urls (ws_env_suffix )
367+ nlm_conn_str = _get_nlm_conn_str ()
368+ has_custom_code_to_execute , code_to_execute = _get_matlab_code_to_execute ()
369+ err = None
368370
369- # MATLAB Proxy gives precedence to the licensing information conveyed
370- # by the user. If MLM_LICENSE_FILE is set, it should be prioritised over
371- # other ways of licensing. But existence of license_info.xml in matlab/licenses
372- # folder may cause hinderance in this workflow. So specifying -licmode as 'file'
373- # overrides license_info.xml and enforces MLM_LICENSE_FILE to be the topmost priority
374-
375- # NLM Connection String provided by MLM_LICENSE_FILE environment variable
376- nlm_conn_str = mwi .validators .validate_mlm_license_file (
377- os .environ .get (mwi_env .get_env_name_network_license_manager ())
378- )
379- matlab_lic_mode = ["-licmode" , "file" ] if nlm_conn_str else ""
380- # flag to hide MATLAB Window
381- flag_to_hide_desktop = ["-nodesktop" ]
382- if system .is_windows ():
383- flag_to_hide_desktop .extend (["-noDisplayDesktop" , "-wait" , "-log" ])
371+ try :
372+ matlab_executable_path , matlab_root_path = get_matlab_executable_and_root_path ()
384373
385- matlab_code_dir = Path (__file__ ).resolve ().parent / "matlab"
386- matlab_startup_file = str (matlab_code_dir / "startup.m" )
387- matlab_code_file = str (matlab_code_dir / "evaluateUserMatlabCode.m" )
374+ except UIVisibleFatalError as error :
375+ logger .error (f"Exception raised during initialization: { error } " )
376+ # Set matlab root and executable path to None as MATLAB root could not be determined
377+ matlab_executable_path = matlab_root_path = None
378+ err = error
388379
389380 matlab_version = get_matlab_version (matlab_root_path )
390-
391- # If the matlab on system PATH is a wrapper script, then it would not be possible to determine MATLAB root (inturn not being able to determine MATLAB version)
392- # unless MWI_CUSTOM_MATLAB_ROOT is set. Raising only a warning as the matlab version is only required for communicating with MHLM.
393- if not matlab_version :
394- logger .warn (
395- f"Could not determine MATLAB version from MATLAB root path: { matlab_root_path } "
396- )
397- logger .warn (
398- f"Set { mwi_env .get_env_name_custom_matlab_root ()} to a valid MATLAB root path"
399- )
400-
401- mpa_flags = (
402- mwi_env .Experimental .get_mpa_flags ()
403- if mwi_env .Experimental .is_mpa_enabled ()
404- else ""
405- )
406- profile_matlab_startup = (
407- "-timing" if mwi_env .Experimental .is_matlab_startup_profiling_enabled () else ""
408- )
409-
410- has_custom_code_to_execute = (
411- len (os .getenv (mwi_env .get_env_name_custom_matlab_code (), "" ).strip ()) > 0
412- )
413-
414- # Sanitize file paths to avoid MATLAB not running the script due to early breakup of character array.
415- mp_code_to_execute = f"try; run('{ _sanitize_file_path_for_matlab (matlab_startup_file )} '); catch MATLABProxyInitializationError; disp(MATLABProxyInitializationError.message); end;"
416- custom_code_to_execute = f"try; run('{ _sanitize_file_path_for_matlab (matlab_code_file )} '); catch MATLABCustomStartupCodeError; disp(MATLABCustomStartupCodeError.message); end;"
417- code_to_execute = (
418- mp_code_to_execute + custom_code_to_execute
419- if has_custom_code_to_execute
420- else mp_code_to_execute
421- )
381+ matlab_version_determined_on_startup = bool (matlab_version )
382+ matlab_cmd = _get_matlab_cmd (matlab_executable_path , code_to_execute , nlm_conn_str )
422383
423384 return {
424- "matlab_path " : matlab_root_path ,
385+ "error " : err ,
425386 "matlab_version" : matlab_version ,
426- "matlab_version_determined_on_startup" : True if matlab_version else False ,
427- "matlab_cmd" : [
428- matlab_executable_path ,
429- "-nosplash" ,
430- * flag_to_hide_desktop ,
431- "-softwareopengl" ,
432- # " v=mvm ",
433- * matlab_lic_mode ,
434- * mpa_flags ,
435- profile_matlab_startup ,
436- "-r" ,
437- code_to_execute ,
438- ],
387+ "matlab_path" : matlab_root_path ,
388+ "matlab_version_determined_on_startup" : matlab_version_determined_on_startup ,
389+ "matlab_cmd" : matlab_cmd ,
439390 "ws_env" : ws_env ,
440- "mwa_api_endpoint" : f"https://login{ ws_env_suffix } .mathworks.com/authenticationws/service/v4" ,
441- "mhlm_api_endpoint" : f"https://licensing{ ws_env_suffix } .mathworks.com/mls/service/v1/entitlement/list" ,
442- "mwa_login" : f"https://login{ ws_env_suffix } .mathworks.com" ,
391+ ** mw_licensing_urls ,
443392 "nlm_conn_str" : nlm_conn_str ,
444393 "has_custom_code_to_execute" : has_custom_code_to_execute ,
445394 }
@@ -646,3 +595,104 @@ def _sanitize_file_path_for_matlab(filepath: str) -> str:
646595 """
647596 filepath_with_single_quotes_escaped = filepath .replace ("'" , "''" )
648597 return filepath_with_single_quotes_escaped
598+
599+
600+ def _get_matlab_code_to_execute ():
601+ """Returns the code that needs to run on MATLAB startup.
602+ Will check for user provided custom MATLAB code and execute it along with the default startup script.
603+
604+ Returns:
605+ tuple: With the first value representing whether there is custom MATLAB code to execute, and the second value representing the MATLAB code to execute.
606+ """
607+ matlab_code_dir = Path (__file__ ).resolve ().parent / "matlab"
608+ matlab_startup_file = str (matlab_code_dir / "startup.m" )
609+ matlab_code_file = str (matlab_code_dir / "evaluateUserMatlabCode.m" )
610+
611+ has_custom_code_to_execute = (
612+ len (os .getenv (mwi_env .get_env_name_custom_matlab_code (), "" ).strip ()) > 0
613+ )
614+
615+ # Sanitize file paths to avoid MATLAB not running the script due to early breakup of character array.
616+ mp_code_to_execute = f"try; run('{ _sanitize_file_path_for_matlab (matlab_startup_file )} '); catch MATLABProxyInitializationError; disp(MATLABProxyInitializationError.message); end;"
617+ custom_code_to_execute = f"try; run('{ _sanitize_file_path_for_matlab (matlab_code_file )} '); catch MATLABCustomStartupCodeError; disp(MATLABCustomStartupCodeError.message); end;"
618+ code_to_execute = (
619+ mp_code_to_execute + custom_code_to_execute
620+ if has_custom_code_to_execute
621+ else mp_code_to_execute
622+ )
623+
624+ return has_custom_code_to_execute , code_to_execute
625+
626+
627+ def _get_nlm_conn_str ():
628+ """Get the Network License Manager (NLM) connection string.
629+
630+ Returns:
631+ str: The NLM connection string provided by the MLM_LICENSE_FILE environment variable.
632+ """
633+ # NLM Connection String provided by MLM_LICENSE_FILE environment variable
634+ nlm_conn_str = mwi .validators .validate_mlm_license_file (
635+ os .environ .get (mwi_env .get_env_name_network_license_manager ())
636+ )
637+
638+ return nlm_conn_str
639+
640+
641+ def _get_mw_licensing_urls (ws_env_suffix ):
642+ """Get the MathWorks licensing URLs.
643+
644+ Args:
645+ ws_env_suffix (str): The environment suffix for the licensing URLs.
646+
647+ Returns:
648+ dict: A dictionary containing the MathWorks licensing URLs for authentication and entitlement.
649+ """
650+ return {
651+ "mwa_api_endpoint" : f"https://login{ ws_env_suffix } .mathworks.com/authenticationws/service/v4" ,
652+ "mhlm_api_endpoint" : f"https://licensing{ ws_env_suffix } .mathworks.com/mls/service/v1/entitlement/list" ,
653+ "mwa_login" : f"https://login{ ws_env_suffix } .mathworks.com" ,
654+ }
655+
656+
657+ def _get_matlab_cmd (matlab_executable_path , code_to_execute , nlm_conn_str ):
658+ """Construct the MATLAB command with appropriate flags and arguments.
659+
660+ Args:
661+ matlab_executable_path (str): The path to the MATLAB executable.
662+ code_to_execute (str): The MATLAB code to execute on startup.
663+ nlm_conn_str (str): The Network License Manager connection string.
664+
665+ Returns:
666+ list: A list of command-line arguments to launch MATLAB with the specified configuration.
667+ """
668+ if not matlab_executable_path :
669+ return None
670+
671+ matlab_lic_mode = ["-licmode" , "file" ] if nlm_conn_str else ""
672+ # flag to hide MATLAB Window
673+ flag_to_hide_desktop = ["-nodesktop" ]
674+ if system .is_windows ():
675+ flag_to_hide_desktop .extend (["-noDisplayDesktop" , "-wait" , "-log" ])
676+
677+ mpa_flags = (
678+ mwi_env .Experimental .get_mpa_flags ()
679+ if mwi_env .Experimental .is_mpa_enabled ()
680+ else ""
681+ )
682+
683+ profile_matlab_startup = (
684+ "-timing" if mwi_env .Experimental .is_matlab_startup_profiling_enabled () else ""
685+ )
686+
687+ return [
688+ matlab_executable_path ,
689+ "-nosplash" ,
690+ * flag_to_hide_desktop ,
691+ "-softwareopengl" ,
692+ # " v=mvm ",
693+ * matlab_lic_mode ,
694+ * mpa_flags ,
695+ profile_matlab_startup ,
696+ "-r" ,
697+ code_to_execute ,
698+ ]
0 commit comments