matlab-proxy 0.5.3__py3-none-any.whl → 0.30.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. matlab_proxy/app.py +578 -205
  2. matlab_proxy/app_state.py +1061 -431
  3. matlab_proxy/constants.py +37 -0
  4. matlab_proxy/default_configuration.py +39 -4
  5. matlab_proxy/devel.py +18 -22
  6. matlab_proxy/gui/index.html +20 -1
  7. matlab_proxy/gui/static/css/index.BedVwcEg.css +10 -0
  8. matlab_proxy/gui/static/js/index.pQwV1obF.js +64 -0
  9. matlab_proxy/gui/static/media/MATLAB-env-blur.NupTbPv_.png +0 -0
  10. matlab_proxy/matlab/evaluateUserMatlabCode.m +51 -0
  11. matlab_proxy/matlab/startup.m +3 -28
  12. matlab_proxy/settings.py +543 -112
  13. matlab_proxy/util/__init__.py +187 -59
  14. matlab_proxy/util/cookie_jar.py +72 -0
  15. matlab_proxy/util/event_loop.py +28 -10
  16. matlab_proxy/util/list_servers.py +71 -26
  17. matlab_proxy/util/mw.py +16 -15
  18. matlab_proxy/util/mwi/download.py +136 -0
  19. matlab_proxy/util/mwi/embedded_connector/__init__.py +1 -1
  20. matlab_proxy/util/mwi/embedded_connector/helpers.py +12 -4
  21. matlab_proxy/util/mwi/embedded_connector/request.py +78 -12
  22. matlab_proxy/util/mwi/environment_variables.py +120 -27
  23. matlab_proxy/util/mwi/exceptions.py +63 -9
  24. matlab_proxy/util/mwi/logger.py +141 -27
  25. matlab_proxy/util/mwi/session_name.py +28 -0
  26. matlab_proxy/util/mwi/token_auth.py +264 -121
  27. matlab_proxy/util/mwi/validators.py +231 -88
  28. matlab_proxy/util/system.py +9 -0
  29. matlab_proxy/util/windows.py +32 -6
  30. {matlab_proxy-0.5.3.dist-info → matlab_proxy-0.30.1.dist-info}/METADATA +94 -49
  31. matlab_proxy-0.30.1.dist-info/RECORD +88 -0
  32. {matlab_proxy-0.5.3.dist-info → matlab_proxy-0.30.1.dist-info}/WHEEL +1 -2
  33. {matlab_proxy-0.5.3.dist-info → matlab_proxy-0.30.1.dist-info}/entry_points.txt +1 -1
  34. matlab_proxy_manager/README.md +85 -0
  35. matlab_proxy_manager/__init__.py +6 -0
  36. matlab_proxy_manager/lib/README.md +53 -0
  37. matlab_proxy_manager/lib/__init__.py +1 -0
  38. matlab_proxy_manager/lib/api.py +419 -0
  39. matlab_proxy_manager/storage/README.md +54 -0
  40. matlab_proxy_manager/storage/__init__.py +1 -0
  41. matlab_proxy_manager/storage/file_repository.py +144 -0
  42. matlab_proxy_manager/storage/interface.py +62 -0
  43. matlab_proxy_manager/storage/server.py +172 -0
  44. matlab_proxy_manager/utils/__init__.py +1 -0
  45. matlab_proxy_manager/utils/auth.py +77 -0
  46. matlab_proxy_manager/utils/constants.py +8 -0
  47. matlab_proxy_manager/utils/decorators.py +37 -0
  48. matlab_proxy_manager/utils/environment_variables.py +51 -0
  49. matlab_proxy_manager/utils/exceptions.py +45 -0
  50. matlab_proxy_manager/utils/helpers.py +314 -0
  51. matlab_proxy_manager/utils/logger.py +76 -0
  52. matlab_proxy_manager/web/README.md +37 -0
  53. matlab_proxy_manager/web/__init__.py +1 -0
  54. matlab_proxy_manager/web/app.py +536 -0
  55. matlab_proxy_manager/web/monitor.py +45 -0
  56. matlab_proxy_manager/web/watcher.py +65 -0
  57. matlab_proxy/gui/asset-manifest.json +0 -23
  58. matlab_proxy/gui/authorization.html +0 -115
  59. matlab_proxy/gui/bootstrap.3.4.1.min.css +0 -6
  60. matlab_proxy/gui/navbar.css +0 -8
  61. matlab_proxy/gui/signin.css +0 -42
  62. matlab_proxy/gui/static/css/main.d890078a.chunk.css +0 -13
  63. matlab_proxy/gui/static/css/main.d890078a.chunk.css.map +0 -1
  64. matlab_proxy/gui/static/js/2.13be6544.chunk.js +0 -3
  65. matlab_proxy/gui/static/js/2.13be6544.chunk.js.LICENSE.txt +0 -59
  66. matlab_proxy/gui/static/js/2.13be6544.chunk.js.map +0 -1
  67. matlab_proxy/gui/static/js/main.c311d854.chunk.js +0 -2
  68. matlab_proxy/gui/static/js/main.c311d854.chunk.js.map +0 -1
  69. matlab_proxy/gui/static/js/runtime-main.f70e4d5f.js +0 -2
  70. matlab_proxy/gui/static/js/runtime-main.f70e4d5f.js.map +0 -1
  71. matlab_proxy/gui/static/media/arrow.0c2968b9.svg +0 -4
  72. matlab_proxy/gui/static/media/feedback.6e8d50eb.svg +0 -1
  73. matlab_proxy/gui/static/media/gripper.9defbc5e.svg +0 -1
  74. matlab_proxy/gui/static/media/help.15e5bfab.svg +0 -1
  75. matlab_proxy/gui/static/media/ico-header-contact-hover.0958c442.svg +0 -17
  76. matlab_proxy/gui/static/media/ico-header-contact.ae9169c8.svg +0 -17
  77. matlab_proxy/gui/static/media/restart.7987508a.svg +0 -1
  78. matlab_proxy/gui/static/media/sign-out.08356b67.svg +0 -1
  79. matlab_proxy/gui/static/media/start.50c4596f.svg +0 -1
  80. matlab_proxy/gui/static/media/stop.30c9a9ab.svg +0 -1
  81. matlab_proxy/gui/static/media/terminate.7ea1363e.svg +0 -1
  82. matlab_proxy/gui/token.html +0 -123
  83. matlab_proxy-0.5.3.dist-info/RECORD +0 -84
  84. matlab_proxy-0.5.3.dist-info/top_level.txt +0 -1
  85. /matlab_proxy/gui/static/media/{glyphicons-halflings-regular.82b1212e.woff → glyphicons-halflings-regular.BKjkU69z.woff} +0 -0
  86. /matlab_proxy/gui/static/media/{glyphicons-halflings-regular.5be1347c.eot → glyphicons-halflings-regular.BUJKDMgK.eot} +0 -0
  87. /matlab_proxy/gui/static/media/{glyphicons-halflings-regular.060b2710.svg → glyphicons-halflings-regular.CSehLiBc.svg} +0 -0
  88. /matlab_proxy/gui/static/media/{glyphicons-halflings-regular.4692b9ec.ttf → glyphicons-halflings-regular.DrwTMapi.ttf} +0 -0
  89. /matlab_proxy/gui/static/media/{glyphicons-halflings-regular.be810be3.woff2 → glyphicons-halflings-regular.DzqM6ju8.woff2} +0 -0
  90. /matlab_proxy/gui/static/media/{ico-header-account-hover.89438e91.svg → ico-header-account-hover.-jQHo6Wx.svg} +0 -0
  91. /matlab_proxy/gui/static/media/{ico-header-account.86b10d7b.svg → ico-header-account.CJCFoo5a.svg} +0 -0
  92. /matlab_proxy/gui/static/media/{ico-sprite.cbdb66c0.png → ico-sprite.DXGLgzq9.png} +0 -0
  93. /matlab_proxy/gui/static/media/{mathworks-eps.4d20e0ee.ttf → mathworks-eps.CGNQALa9.ttf} +0 -0
  94. /matlab_proxy/gui/static/media/{mathworks-eps.df1428df.svg → mathworks-eps.DrkCtQtG.svg} +0 -0
  95. /matlab_proxy/gui/static/media/{mathworks-eps.e5c41e84.woff → mathworks-eps.Ds7lQbql.woff} +0 -0
  96. /matlab_proxy/gui/static/media/{mathworks-pictograms.3fc6513a.woff → mathworks-pictograms.BdqxEfBR.woff} +0 -0
  97. /matlab_proxy/gui/static/media/{mathworks-pictograms.f6f087b0.svg → mathworks-pictograms.CCLweoD4.svg} +0 -0
  98. /matlab_proxy/gui/static/media/{mathworks-pictograms.6e128c0e.ttf → mathworks-pictograms.DZhFdRSm.ttf} +0 -0
  99. /matlab_proxy/gui/static/media/{mathworks.80a3218e.svg → mathworks.C-qsbhDy.svg} +0 -0
  100. /matlab_proxy/gui/static/media/{mathworks.c422935b.ttf → mathworks.Ceplx86V.ttf} +0 -0
  101. /matlab_proxy/gui/static/media/{mathworks.37a563ef.woff → mathworks.D08X1Vp8.woff} +0 -0
  102. /matlab_proxy/gui/static/media/{trigger-error.3f1c4ef2.svg → trigger-error.QEdsGL-m.svg} +0 -0
  103. /matlab_proxy/gui/static/media/{trigger-ok.7b9c238b.svg → trigger-ok.Dzg8OIrk.svg} +0 -0
  104. {matlab_proxy-0.5.3.dist-info → matlab_proxy-0.30.1.dist-info/licenses}/LICENSE.md +0 -0
@@ -0,0 +1,136 @@
1
+ # Copyright 2024-2025 The MathWorks, Inc.
2
+
3
+ # This file contains functions required to enable downloads from the file browser
4
+ from matlab_proxy.util.mwi import logger as mwi_logger
5
+ from matlab_proxy.util import mwi, system
6
+
7
+ logger = mwi_logger.get()
8
+
9
+
10
+ def _is_null_base_url(base_url):
11
+ return base_url == "/" or base_url == ""
12
+
13
+
14
+ def is_download_request(req):
15
+ """
16
+ Determine if the incoming request is for a download action.
17
+
18
+ This function checks if the request's relative URL path starts with
19
+ '/download/' or with '{base_url}/download/', depending on the base URL
20
+ specified in the application settings.
21
+
22
+ Parameters:
23
+ req (HTTPRequest): HTTPRequest Object
24
+
25
+ Returns:
26
+ - bool: True if the request is for a download, False otherwise.
27
+ ```
28
+ """
29
+
30
+ base_url = req.app["settings"]["base_url"]
31
+ if _is_null_base_url(base_url):
32
+ return req.rel_url.path.startswith("/download")
33
+ else:
34
+ return req.rel_url.path.startswith(f"{base_url}/download")
35
+
36
+
37
+ async def get_download_url(req):
38
+ """
39
+ Asynchronously generates a download URL for a file.
40
+
41
+ This function takes a request object, extracts the full path to the file, and
42
+ uses the MATLAB Web Interface (MWI) to generate a download URL for that file.
43
+ It logs the full path and the response from the MWI. If successful, it returns
44
+ the download URL; otherwise, it returns None.
45
+
46
+ Parameters:
47
+ The request object containing necessary information to process the download.
48
+ Returns:
49
+ The download URL string if successful, None otherwise.
50
+ Raises:
51
+ Logs an error message and returns None if an error occurs.
52
+ """
53
+ full_path_to_file = _get_download_payload_path(req)
54
+ logger.debug(f"full_path_to_file: {full_path_to_file}")
55
+
56
+ args = [full_path_to_file, 1.0]
57
+ data = mwi.embedded_connector.helpers.get_data_to_feval_mcode(
58
+ "matlab.ui.internal.URLUtils.getURLToUserFile", *args, nargout=1
59
+ )
60
+
61
+ try:
62
+ state = req.app["state"]
63
+ headers = state._get_token_auth_headers()
64
+ url = mwi.embedded_connector.helpers.get_mvm_endpoint(
65
+ state.settings["mwi_server_url"]
66
+ )
67
+ resp_json = await mwi.embedded_connector.send_request(
68
+ url=url,
69
+ method="POST",
70
+ data=data,
71
+ headers=headers,
72
+ )
73
+
74
+ logger.debug(f"EC Response URL: {resp_json}")
75
+
76
+ resp = resp_json["messages"]["FEvalResponse"][0]
77
+
78
+ if not resp["isError"]:
79
+ # No error detected, proceed to fetch the results
80
+ download_url = resp["results"][0]
81
+ logger.debug(f"download_url: {download_url}")
82
+ base_url = req.app["settings"]["base_url"]
83
+ return (
84
+ download_url
85
+ if _is_null_base_url(base_url)
86
+ else f"{base_url}{download_url}"
87
+ )
88
+
89
+ except KeyError as key_err:
90
+ logger.error(f"Invalid Key Usage Detected! Check key: {key_err}")
91
+ pass
92
+
93
+ except Exception as err:
94
+ logger.error(
95
+ f"Failed to create download url from the Embedded Connector due to err: {err}"
96
+ )
97
+ pass
98
+
99
+ # In case of any failures.
100
+ return None
101
+
102
+
103
+ def _get_download_payload_path(req):
104
+ """
105
+ Constructs the file system path to the payload for a download request.
106
+
107
+ This function analyzes the incoming request to determine the intended file path
108
+ for download. It takes into account the base URL from the application settings,
109
+ the nature of the request (whether it's a download request), and the operating
110
+ system to format the path correctly. The function supports different path
111
+ formatting for Windows and Unix-like systems due to their differences in file
112
+ system path syntax.
113
+
114
+ Note:
115
+ This function is intended to be used internally and starts with an underscore
116
+ to indicate it is a private member of the module.
117
+
118
+ Args:
119
+ req: An object representing the incoming request, which includes the relative
120
+ URL from which the file path can be deduced.
121
+
122
+ Returns:
123
+ A string representing the file system path to the requested download payload,
124
+ or None if the request is not a download request.
125
+ """
126
+ base_url = req.app["settings"]["base_url"]
127
+ if is_download_request(req):
128
+ from pathlib import Path
129
+
130
+ compare_str = (
131
+ "/download" if _is_null_base_url(base_url) else f"{base_url}/download"
132
+ )
133
+
134
+ return str(req.rel_url.path).replace(compare_str, "", 1)
135
+
136
+ return None
@@ -1,4 +1,4 @@
1
1
  # Copyright (c) 2020-2022 The MathWorks, Inc.
2
2
 
3
3
  from . import helpers
4
- from .request import get_state, send_request
4
+ from .request import get_busy_state, send_request
@@ -1,8 +1,7 @@
1
- # Copyright (c) 2020-2022 The MathWorks, Inc.
2
-
3
- """ This file contains helper methods which return the details required for sending
4
- a HTTP request to the Embedded Connector. """
1
+ # Copyright 2020-2024 The MathWorks, Inc.
5
2
 
3
+ """This file contains helper methods which return the details required for sending
4
+ a HTTP request to the Embedded Connector."""
6
5
 
7
6
  from matlab_proxy.util import mwi
8
7
  from matlab_proxy.util.mwi import environment_variables as mwi_env
@@ -46,6 +45,15 @@ def get_data_for_ping_request():
46
45
  return {"messages": {"Ping": [{}]}}
47
46
 
48
47
 
48
+ def get_data_for_matlab_busy_status_request():
49
+ """Returns data required to send in the payload for a MATLAB busy/idle status request to the embedded connector
50
+
51
+ Returns:
52
+ dict: Payload data
53
+ """
54
+ return {"messages": {"GetMatlabStatus": [{}]}}
55
+
56
+
49
57
  def get_data_to_eval_mcode(m_code):
50
58
  """Returns the data required to send in the payload for evaluating mcode using eval function to the embedded connector.
51
59
 
@@ -1,6 +1,6 @@
1
- # Copyright (c) 2020-2022 The MathWorks, Inc.
1
+ # Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
- """
3
+ """
4
4
  This file contains the methods to communicate with the embedded connector.
5
5
  """
6
6
 
@@ -8,7 +8,15 @@ import json
8
8
 
9
9
  from matlab_proxy.util.mwi.exceptions import EmbeddedConnectorError
10
10
 
11
- from .helpers import get_data_for_ping_request, get_ping_endpoint
11
+ from matlab_proxy.util import mwi
12
+
13
+ logger = mwi.logger.get()
14
+
15
+ from .helpers import (
16
+ get_data_for_ping_request,
17
+ get_data_for_matlab_busy_status_request,
18
+ get_ping_endpoint,
19
+ )
12
20
 
13
21
 
14
22
  async def send_request(url: str, data: dict, method: str, headers: dict = None) -> dict:
@@ -38,12 +46,16 @@ async def send_request(url: str, data: dict, method: str, headers: dict = None)
38
46
  data = json.dumps(data)
39
47
 
40
48
  try:
41
- async with aiohttp.ClientSession() as session:
49
+ async with aiohttp.ClientSession(trust_env=True) as session:
50
+ logger.debug(
51
+ f"sending request: method={method}, url={url}, data={data}, headers={headers}, "
52
+ )
53
+
42
54
  async with session.request(
43
- method=method, url=url, data=data, headers=None, ssl=False
55
+ method=method, url=url, data=data, headers=headers, ssl=False
44
56
  ) as resp:
45
- if resp.reason != "OK":
46
-
57
+ logger.debug(f"response from endpoint{url} and resp={resp}")
58
+ if not resp.ok:
47
59
  # Converting to dict and formatting for printing
48
60
  data = json.loads(data)
49
61
 
@@ -56,22 +68,76 @@ async def send_request(url: str, data: dict, method: str, headers: dict = None)
56
68
  raise err
57
69
 
58
70
 
59
- async def get_state(mwi_server_url):
71
+ async def get_state(mwi_server_url, headers=None):
60
72
  """Returns the state of MATLAB's Embedded Connector.
61
73
 
62
74
  Args:
63
75
  port (int): The port on which the embedded connector is running at
64
-
76
+ headers: Headers to include with the request
65
77
  Returns:
66
78
  str: Either "up" or "down"
67
79
  """
68
80
  data = get_data_for_ping_request()
69
81
  url = get_ping_endpoint(mwi_server_url)
82
+
70
83
  try:
71
- resp = await send_request(url=url, data=data, method="POST")
84
+ resp = await send_request(
85
+ url=url,
86
+ data=data,
87
+ method="POST",
88
+ headers=headers,
89
+ )
90
+
91
+ # Any changes in response from embedded connector would be caught by KeyError
72
92
  if not resp["messages"]["PingResponse"][0]["messageFaults"]:
73
93
  return "up"
74
- except Exception:
75
- pass
94
+
95
+ except KeyError as key_err:
96
+ logger.error(f"Invalid Key Usage Detected! Check key: {key_err}")
97
+
98
+ except Exception as err:
99
+ logger.debug(
100
+ f"{err}: Embbeded connector is currently not responding to ping requests."
101
+ )
76
102
 
77
103
  return "down"
104
+
105
+
106
+ async def get_busy_state(mwi_server_url, headers=None):
107
+ """Returns the state of MATLAB's Embedded Connector.
108
+
109
+ Args:
110
+ port (int): The port on which the embedded connector is running at
111
+ headers: Headers to include with the request
112
+ Returns:
113
+ str: Either "idle" or "busy" when a valid response is received. Else None is returned.
114
+ """
115
+ data = get_data_for_matlab_busy_status_request()
116
+ url = get_ping_endpoint(mwi_server_url)
117
+
118
+ busy_status = None
119
+
120
+ try:
121
+ resp = await send_request(
122
+ url=url,
123
+ data=data,
124
+ method="POST",
125
+ headers=headers,
126
+ )
127
+
128
+ busy_status = resp["messages"]["GetMatlabStatusResponse"][0]["status"].lower()
129
+
130
+ assert busy_status in [
131
+ "idle",
132
+ "busy",
133
+ ], f"Was expecting MATLAB busy status to be either 'idle' or 'busy', but received {busy_status} instead."
134
+
135
+ except KeyError as key_err:
136
+ logger.error(f"Invalid Key Usage Detected! Check key: {key_err}")
137
+
138
+ except Exception as err:
139
+ logger.debug(
140
+ f"{err}: Embedded connector is currently not responding to ping requests."
141
+ )
142
+
143
+ return busy_status
@@ -1,9 +1,33 @@
1
- # Copyright (c) 2020-2022 The MathWorks, Inc.
1
+ # Copyright 2020-2025 The MathWorks, Inc.
2
2
  """This file lists and exposes the environment variables which are used by the integration."""
3
3
 
4
4
  import os
5
5
 
6
6
 
7
+ def _is_env_set_to_true(env_name: str) -> bool:
8
+ """Helper function that returns True if the environment variable specified is set to True.
9
+
10
+ Args:
11
+ env_name (str): Name of the environment variable to check the state for.
12
+
13
+ Returns:
14
+ bool: True if the value of the environment variable is a case insensitive match to the string "True"
15
+ """
16
+ return os.environ.get(env_name, "false").lower() == "true"
17
+
18
+
19
+ def _is_env_set_to_false(env_name: str) -> bool:
20
+ """Helper function that returns True if the environment variable specified is set to False.
21
+
22
+ Args:
23
+ env_name (str): Name of the environment variable to check the state for.
24
+
25
+ Returns:
26
+ bool: True if the value of the environment variable is a case insensitive match to the string "False"
27
+ """
28
+ return os.environ.get(env_name, "").lower() == "false"
29
+
30
+
7
31
  def get_env_name_network_license_manager():
8
32
  """Specifies the path to valid license file or address of a network license server"""
9
33
  return "MLM_LICENSE_FILE"
@@ -20,19 +44,10 @@ def get_env_name_logging_level():
20
44
 
21
45
 
22
46
  def get_env_name_enable_web_logging():
23
- """wef > v0.2.10 Enable the logging of asyncio web traffic by setting to true"""
47
+ """Enable the logging of asyncio web traffic by setting to true"""
24
48
  return "MWI_ENABLE_WEB_LOGGING"
25
49
 
26
50
 
27
- def get_old_env_name_enable_web_logging():
28
- """
29
- Enable the logging of asyncio web traffic by setting to true
30
- This name is deprecated and was last published in version v0.2.10 of matlab-proxy.
31
- """
32
-
33
- return "MWI_WEB_LOGGING_ENABLED"
34
-
35
-
36
51
  def get_env_name_log_file():
37
52
  """Specifies a file into which logging content is directed"""
38
53
  return "MWI_LOG_FILE"
@@ -89,32 +104,22 @@ def get_env_name_matlab_tempdir():
89
104
 
90
105
  def is_development_mode_enabled():
91
106
  """Returns true if the app is in development mode."""
92
- return os.environ.get(get_env_name_development(), "false").lower() == "true"
107
+ return _is_env_set_to_true(get_env_name_development())
93
108
 
94
109
 
95
110
  def is_testing_mode_enabled():
96
111
  """Returns true if the app is in testing mode."""
97
- return (
98
- is_development_mode_enabled()
99
- and os.environ.get(get_env_name_testing(), "false").lower() == "true"
100
- )
112
+ return is_development_mode_enabled() and _is_env_set_to_true(get_env_name_testing())
101
113
 
102
114
 
103
115
  def is_web_logging_enabled():
104
116
  """Returns true if the web logging is required to be enabled"""
117
+ return _is_env_set_to_true(get_env_name_enable_web_logging())
105
118
 
106
- if os.environ.get(get_old_env_name_enable_web_logging(), None) is not None:
107
- from matlab_proxy.util import mwi
108
119
 
109
- logger = mwi.logger.get()
110
- logger.warning(
111
- f"Usage of {get_old_env_name_enable_web_logging()} is being deprecated from v0.2.10 and will be removed in a future release.\n Use {get_env_name_enable_web_logging()} instead. "
112
- )
113
- return (
114
- os.environ.get(get_old_env_name_enable_web_logging(), "false").lower()
115
- == "true"
116
- )
117
- return os.environ.get(get_env_name_enable_web_logging(), "false").lower() == "true"
120
+ def get_env_name_enable_ssl():
121
+ """Returns the environment variable used for enabling/disabling SSL/TLS communication."""
122
+ return "MWI_ENABLE_SSL"
118
123
 
119
124
 
120
125
  def get_env_name_ssl_cert_file():
@@ -135,3 +140,91 @@ def get_env_name_enable_mwi_auth_token():
135
140
  def get_env_name_mwi_auth_token():
136
141
  """User specified token for use with Token-Based Authentication"""
137
142
  return "MWI_AUTH_TOKEN"
143
+
144
+
145
+ def get_env_name_matlab_log_dir():
146
+ """Returns the key used for MATLAB log dir env variable"""
147
+ return "MATLAB_LOG_DIR"
148
+
149
+
150
+ def get_env_name_mwi_use_existing_license():
151
+ """Returns the environment variable name used to instruct matlab-proxy to use an existing license. Usually used by already activated MATLAB installations."""
152
+ return "MWI_USE_EXISTING_LICENSE"
153
+
154
+
155
+ def get_env_name_custom_matlab_root():
156
+ """User specified path to MATLAB root"""
157
+ return "MWI_CUSTOM_MATLAB_ROOT"
158
+
159
+
160
+ def get_env_name_process_startup_timeout():
161
+ """User specified timeout in seconds for processes launched by matlab-proxy"""
162
+ return "MWI_PROCESS_START_TIMEOUT"
163
+
164
+
165
+ def get_env_name_custom_matlab_code():
166
+ """User specified MATLAB code that will be executed by matlab-proxy upon its start"""
167
+ return "MWI_MATLAB_STARTUP_SCRIPT"
168
+
169
+
170
+ def get_env_name_shutdown_on_idle_timeout():
171
+ """User specified timeout in minutes for shutdown on idle of matlab-proxy"""
172
+ return "MWI_SHUTDOWN_ON_IDLE_TIMEOUT"
173
+
174
+
175
+ def get_env_name_session_name():
176
+ """User specified session name for the MATLAB Proxy instance, used to set the browser title."""
177
+ return "MWI_SESSION_NAME"
178
+
179
+
180
+ class Experimental:
181
+ """This class houses functions which are undocumented APIs and Environment variables.
182
+ Note: Never add any state to this class. Its only intended for use as an abstraction layer
183
+ for functions which are not ready for prime time.
184
+ """
185
+
186
+ @staticmethod
187
+ def get_env_name_enable_simulink():
188
+ """Returns the environment variable name used to enable simulink support"""
189
+ ##NOTE: Simulink Online is unavailable for general use as of R2023b.
190
+ return "MWI_ENABLE_SIMULINK"
191
+
192
+ @staticmethod
193
+ def is_simulink_enabled():
194
+ """Returns true if the simulink online is enabled."""
195
+ return _is_env_set_to_true(Experimental.get_env_name_enable_simulink())
196
+
197
+ @staticmethod
198
+ def get_env_name_profile_matlab_startup():
199
+ """Returns the environment variable name used to enable MPA support"""
200
+ return "MWI_PROFILE_MATLAB_STARTUP"
201
+
202
+ @staticmethod
203
+ def is_matlab_startup_profiling_enabled():
204
+ """Returns true if the startup profiling is enabled."""
205
+ return _is_env_set_to_true(Experimental.get_env_name_profile_matlab_startup())
206
+
207
+ @staticmethod
208
+ def get_env_name_use_cookie_cache():
209
+ """Returns the environment variable name used to enable cookie jar support for matlab-proxy"""
210
+ return "MWI_USE_COOKIE_CACHE"
211
+
212
+ @staticmethod
213
+ def should_use_cookie_cache():
214
+ """Returns true if the cookie jar support is enabled."""
215
+ return _is_env_set_to_true(Experimental.get_env_name_use_cookie_cache())
216
+
217
+ @staticmethod
218
+ def get_env_name_use_rich_logging():
219
+ """Set to True to enable rich logging to console."""
220
+ return "MWI_USE_RICH_LOGGING"
221
+
222
+ @staticmethod
223
+ def use_rich_logger():
224
+ """Returns true if the cookie jar support is enabled."""
225
+ return _is_env_set_to_true(Experimental.get_env_name_use_rich_logging())
226
+
227
+ @staticmethod
228
+ def get_licmode_override():
229
+ """Returns the licmode oveerride if set"""
230
+ return os.environ.get("MWI_LICMODE_OVERRIDE", None)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020-2022 The MathWorks, Inc.
1
+ # Copyright 2020-2025 The MathWorks, Inc.
2
2
 
3
3
 
4
4
  class AppError(Exception):
@@ -17,9 +17,19 @@ class AppError(Exception):
17
17
  self.stacktrace = stacktrace
18
18
 
19
19
 
20
- class InternalError(AppError):
21
- """A Class which inherits the AppError class.
22
- This class represents any Internal Error within the App
20
+ class FatalError(AppError):
21
+ """An error which indicates that matlab-proxy web server cannot be brought up.
22
+ Args:
23
+ AppError (Class): Parent Class containing attributes to store
24
+ messages, logs and stacktrace.
25
+ """
26
+
27
+ pass
28
+
29
+
30
+ class UIVisibleFatalError(AppError):
31
+ """A Class with inherits from the AppError class.
32
+ This class is used to represent Fatal Errors which need to be propagated to the front end.
23
33
 
24
34
  Args:
25
35
  AppError (Class): Parent Class containing attributes to store
@@ -29,7 +39,7 @@ class InternalError(AppError):
29
39
  pass
30
40
 
31
41
 
32
- class MatlabInstallError(AppError):
42
+ class MatlabInstallError(UIVisibleFatalError):
33
43
  """A Class which inherits the AppError class.
34
44
 
35
45
  This class represents errors with MATLAB Installation.
@@ -129,6 +139,19 @@ class XvfbError(AppError):
129
139
  pass
130
140
 
131
141
 
142
+ class WindowManagerError(AppError):
143
+ """A Class which inherits the AppError class.
144
+
145
+ This class represents any errors raised when instantiating a Window Manager within the Xvfb DISPLAY.
146
+
147
+ Args:
148
+ AppError (Class): Parent Class containing attributes to store
149
+ messages, logs and stacktrace.
150
+ """
151
+
152
+ pass
153
+
154
+
132
155
  class EmbeddedConnectorError(MatlabError):
133
156
  """A Class which inherits the MatlabError class.
134
157
 
@@ -142,6 +165,34 @@ class EmbeddedConnectorError(MatlabError):
142
165
  pass
143
166
 
144
167
 
168
+ class InvalidTokenError(AppError):
169
+ """A Class which inherits the AppError class.
170
+
171
+ This class represents token authentication errors.
172
+
173
+ Args:
174
+ AppError (Class): Parent Class containing attributes to store
175
+ messages, logs and stacktrace.
176
+ """
177
+
178
+ pass
179
+
180
+
181
+ class LockAcquisitionError(Exception):
182
+ """Exception raised when a lock is not properly acquired before modifying a variable.
183
+
184
+ This error is thrown in scenarios where:
185
+ 1) A lock must be acquired before modifying a shared resource, but it wasn't.
186
+ 2) The lock for a shared resource was acquired by one function, but another function attempts to modify the resource without holding the lock.
187
+
188
+
189
+ Args:
190
+ Exception : Python's inbuilt Exception Class.
191
+ """
192
+
193
+ pass
194
+
195
+
145
196
  def log_error(logger, err: Exception):
146
197
  """Logs any error to stdout.
147
198
 
@@ -150,7 +201,10 @@ def log_error(logger, err: Exception):
150
201
  err (Class): An instance of one of the Error classes as defined above.
151
202
  Example: OnlineLicensingError, EntitlementError
152
203
  """
153
- logs_str = ("\n" + "\n".join(err.logs)) if err.logs is not None else ""
154
- logger.error(
155
- err.message if err.message else "An Exception was raised:\n" + logs_str
156
- )
204
+ if isinstance(err, AppError):
205
+ logs_str = ("\n" + "\n".join(err.logs)) if err.logs is not None else ""
206
+ logger.error(
207
+ err.message if err.message else "An Exception was raised:\n" + logs_str
208
+ )
209
+ else:
210
+ logger.error(err)