matlab-proxy 0.24.1__py3-none-any.whl → 0.25.0__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.
Potentially problematic release.
This version of matlab-proxy might be problematic. Click here for more details.
- matlab_proxy/app.py +1 -3
- matlab_proxy/app_state.py +56 -21
- matlab_proxy/constants.py +2 -1
- matlab_proxy/gui/index.html +1 -1
- matlab_proxy/gui/static/js/index.qK3VCGVb.js +64 -0
- matlab_proxy/matlab/startup.m +1 -4
- matlab_proxy/settings.py +145 -91
- matlab_proxy/util/mwi/environment_variables.py +2 -27
- matlab_proxy/util/mwi/exceptions.py +14 -1
- matlab_proxy/util/mwi/validators.py +19 -11
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/METADATA +32 -20
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/RECORD +25 -25
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/WHEEL +1 -1
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/entry_points.txt +0 -1
- tests/integration/integration_tests_with_license/test_http_end_points.py +4 -5
- tests/unit/test_app.py +94 -45
- tests/unit/test_app_state.py +37 -9
- tests/unit/test_non_dev_mode.py +4 -4
- tests/unit/test_settings.py +175 -11
- tests/unit/util/mwi/test_token_auth.py +5 -5
- tests/unit/util/mwi/test_validators.py +12 -7
- tests/unit/util/test_mw.py +2 -2
- tests/unit/util/test_util.py +7 -7
- matlab_proxy/gui/static/js/index.Cm14Eqsb.js +0 -64
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/LICENSE.md +0 -0
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/top_level.txt +0 -0
matlab_proxy/app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2020-
|
|
1
|
+
# Copyright 2020-2025 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import json
|
|
@@ -197,8 +197,6 @@ async def get_env_config(req):
|
|
|
197
197
|
state = req.app["state"]
|
|
198
198
|
config = state.settings["env_config"]
|
|
199
199
|
|
|
200
|
-
config["useMOS"] = mwi_env.Experimental.should_use_mos_html()
|
|
201
|
-
config["useMRE"] = mwi_env.Experimental.should_use_mre_html()
|
|
202
200
|
config["isConcurrencyEnabled"] = IS_CONCURRENCY_CHECK_ENABLED
|
|
203
201
|
# In a previously authenticated session, if the url is accessed without the token(using session cookie), send the token as well.
|
|
204
202
|
config["authentication"] = {
|
matlab_proxy/app_state.py
CHANGED
|
@@ -10,15 +10,15 @@ import time
|
|
|
10
10
|
import uuid
|
|
11
11
|
from collections import deque
|
|
12
12
|
from datetime import datetime, timedelta, timezone
|
|
13
|
-
from typing import Final, Optional
|
|
13
|
+
from typing import Callable, Final, Optional
|
|
14
14
|
|
|
15
15
|
from matlab_proxy import util
|
|
16
16
|
from matlab_proxy.constants import (
|
|
17
|
+
CHECK_MATLAB_STATUS_INTERVAL_SECONDS,
|
|
17
18
|
CONNECTOR_SECUREPORT_FILENAME,
|
|
18
19
|
IS_CONCURRENCY_CHECK_ENABLED,
|
|
19
20
|
MATLAB_LOGS_FILE_NAME,
|
|
20
21
|
USER_CODE_OUTPUT_FILE_NAME,
|
|
21
|
-
CHECK_MATLAB_STATUS_INTERVAL_SECONDS,
|
|
22
22
|
)
|
|
23
23
|
from matlab_proxy.settings import get_process_startup_timeout
|
|
24
24
|
from matlab_proxy.util import mw, mwi, system, windows
|
|
@@ -30,10 +30,11 @@ from matlab_proxy.util.mwi.exceptions import (
|
|
|
30
30
|
FatalError,
|
|
31
31
|
LicensingError,
|
|
32
32
|
MatlabError,
|
|
33
|
+
MatlabInstallError,
|
|
33
34
|
OnlineLicensingError,
|
|
34
35
|
UIVisibleFatalError,
|
|
35
36
|
XvfbError,
|
|
36
|
-
|
|
37
|
+
WindowManagerError,
|
|
37
38
|
log_error,
|
|
38
39
|
)
|
|
39
40
|
|
|
@@ -90,10 +91,6 @@ class AppState:
|
|
|
90
91
|
self.error = settings["error"]
|
|
91
92
|
self.warnings = settings["warnings"]
|
|
92
93
|
|
|
93
|
-
if self.error is not None:
|
|
94
|
-
self.logs["matlab"].clear()
|
|
95
|
-
return
|
|
96
|
-
|
|
97
94
|
# Keep track of when the Embedded connector starts.
|
|
98
95
|
# Would be initialized appropriately by get_embedded_connector_state() task.
|
|
99
96
|
self.embedded_connector_start_time = None
|
|
@@ -552,7 +549,7 @@ class AppState:
|
|
|
552
549
|
|
|
553
550
|
if system.is_linux():
|
|
554
551
|
# If Xvfb is on system PATH, check if it up and running.
|
|
555
|
-
if self.settings
|
|
552
|
+
if self.settings.get("is_xvfb_available", None) and (
|
|
556
553
|
xvfb_process is None or xvfb_process.returncode is not None
|
|
557
554
|
):
|
|
558
555
|
logger.debug(
|
|
@@ -998,17 +995,11 @@ class AppState:
|
|
|
998
995
|
# The mwi_logs_dir is where MATLAB will write any subsequent logs
|
|
999
996
|
matlab_env["MATLAB_LOG_DIR"] = str(self.mwi_logs_dir)
|
|
1000
997
|
|
|
1001
|
-
# Set MW_CONNECTOR_CONTEXT_ROOT
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
)
|
|
1007
|
-
|
|
1008
|
-
# Setup Simulink Online which requires a pre-warm stage
|
|
1009
|
-
if mwi_env.Experimental.is_simulink_enabled():
|
|
1010
|
-
logger.info("Enabling usage of Simulink Online...")
|
|
1011
|
-
matlab_env["PREWARM_SIMULINK"] = "true"
|
|
998
|
+
# Set MW_CONNECTOR_CONTEXT_ROOT
|
|
999
|
+
matlab_env["MW_CONNECTOR_CONTEXT_ROOT"] = self.settings.get("base_url", "/")
|
|
1000
|
+
logger.info(
|
|
1001
|
+
f"MW_CONNECTOR_CONTEXT_ROOT is set to: {matlab_env['MW_CONNECTOR_CONTEXT_ROOT']}"
|
|
1002
|
+
)
|
|
1012
1003
|
|
|
1013
1004
|
# Env setup related to logging
|
|
1014
1005
|
# Very verbose logging in debug mode
|
|
@@ -1057,6 +1048,31 @@ class AppState:
|
|
|
1057
1048
|
key: value for key, value in env_vars.items() if not key.startswith(prefix)
|
|
1058
1049
|
}
|
|
1059
1050
|
|
|
1051
|
+
async def __start_window_manager(self, display=None):
|
|
1052
|
+
if display is None:
|
|
1053
|
+
logger.info("Not starting fluxbox as display is not provided")
|
|
1054
|
+
return None
|
|
1055
|
+
|
|
1056
|
+
wm_env = os.environ.copy()
|
|
1057
|
+
wm_env["DISPLAY"] = display
|
|
1058
|
+
wm_cmd = ["fluxbox", "-screen", "0", "-log", "/dev/null"]
|
|
1059
|
+
|
|
1060
|
+
try:
|
|
1061
|
+
logger.info(f"Starting window manager with DISPLAY={wm_env['DISPLAY']}")
|
|
1062
|
+
return await asyncio.create_subprocess_exec(
|
|
1063
|
+
*wm_cmd, close_fds=False, env=wm_env, stderr=asyncio.subprocess.PIPE
|
|
1064
|
+
)
|
|
1065
|
+
|
|
1066
|
+
except Exception as err:
|
|
1067
|
+
self.error = WindowManagerError(
|
|
1068
|
+
"Unable to start the Fluxbox Window Manager due to the following error: "
|
|
1069
|
+
+ err
|
|
1070
|
+
)
|
|
1071
|
+
# Log the error on the console.
|
|
1072
|
+
log_error(logger, self.error)
|
|
1073
|
+
|
|
1074
|
+
return None
|
|
1075
|
+
|
|
1060
1076
|
async def __start_xvfb_process(self):
|
|
1061
1077
|
"""Private method to start the xvfb process. Will set appropriate
|
|
1062
1078
|
errors to self.error and return None when any exceptions are raised.
|
|
@@ -1078,7 +1094,7 @@ class AppState:
|
|
|
1078
1094
|
)
|
|
1079
1095
|
self.settings["matlab_display"] = ":" + str(display_port)
|
|
1080
1096
|
|
|
1081
|
-
logger.
|
|
1097
|
+
logger.info(f"Started Xvfb with PID={xvfb.pid} on DISPLAY={display_port}")
|
|
1082
1098
|
|
|
1083
1099
|
return xvfb
|
|
1084
1100
|
|
|
@@ -1109,6 +1125,12 @@ class AppState:
|
|
|
1109
1125
|
Returns:
|
|
1110
1126
|
(asyncio.subprocess.Process | psutil.Process): If process creation is successful, else return None.
|
|
1111
1127
|
"""
|
|
1128
|
+
# If there's no matlab_cmd available, it means that MATLAB is not available on system PATH.
|
|
1129
|
+
if not self.settings["matlab_cmd"]:
|
|
1130
|
+
raise MatlabInstallError(
|
|
1131
|
+
"Unable to find MATLAB on the system PATH. Add MATLAB to the system PATH, and restart matlab-proxy."
|
|
1132
|
+
)
|
|
1133
|
+
|
|
1112
1134
|
if system.is_posix():
|
|
1113
1135
|
import pty
|
|
1114
1136
|
|
|
@@ -1302,7 +1324,13 @@ class AppState:
|
|
|
1302
1324
|
|
|
1303
1325
|
self.processes["xvfb"] = xvfb
|
|
1304
1326
|
|
|
1327
|
+
# Start Window Manager on linux if possible
|
|
1328
|
+
if system.is_linux() and self.settings["is_windowmanager_available"]:
|
|
1329
|
+
display = self.settings.get("matlab_display", None)
|
|
1330
|
+
await self.__start_window_manager(display)
|
|
1331
|
+
|
|
1305
1332
|
try:
|
|
1333
|
+
|
|
1306
1334
|
# Prepare ready file for the MATLAB process.
|
|
1307
1335
|
self.create_logs_dir_for_MATLAB()
|
|
1308
1336
|
|
|
@@ -1328,7 +1356,14 @@ class AppState:
|
|
|
1328
1356
|
# Start MATLAB Process
|
|
1329
1357
|
logger.debug("Starting MATLAB")
|
|
1330
1358
|
|
|
1331
|
-
|
|
1359
|
+
try:
|
|
1360
|
+
matlab = await self.__start_matlab_process(matlab_env)
|
|
1361
|
+
|
|
1362
|
+
# If there's an error with starting MATLAB, set the error to the state and matlab to None
|
|
1363
|
+
except MatlabInstallError as err:
|
|
1364
|
+
log_error(logger, err)
|
|
1365
|
+
self.error = err
|
|
1366
|
+
matlab = None
|
|
1332
1367
|
|
|
1333
1368
|
# Release the lock after MATLAB process has started.
|
|
1334
1369
|
await self.matlab_state_updater_lock.release()
|
matlab_proxy/constants.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2023-
|
|
1
|
+
# Copyright 2023-2025 The MathWorks, Inc.
|
|
2
2
|
from typing import Final, List
|
|
3
3
|
|
|
4
4
|
"""This module defines project-level constants"""
|
|
@@ -24,6 +24,7 @@ SUPPORTED_MATLAB_VERSIONS: Final[List[str]] = [
|
|
|
24
24
|
"R2023b",
|
|
25
25
|
"R2024a",
|
|
26
26
|
"R2024b",
|
|
27
|
+
"R2025a",
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
# This constant when set to True restricts the number of active sessions to one
|
matlab_proxy/gui/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<meta name="internal_mw_identifier" content="MWI_MATLAB_PROXY_IDENTIFIER" />
|
|
12
12
|
<link rel="manifest" href="./manifest.json" />
|
|
13
13
|
<title>MATLAB</title>
|
|
14
|
-
<script type="module" crossorigin src="./static/js/index.
|
|
14
|
+
<script type="module" crossorigin src="./static/js/index.qK3VCGVb.js"></script>
|
|
15
15
|
<link rel="stylesheet" crossorigin href="./static/css/index.BSVLACuY.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|