matlab-proxy 0.18.1__py3-none-any.whl → 0.19.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 +54 -43
- matlab_proxy/app_state.py +370 -155
- matlab_proxy/constants.py +3 -0
- matlab_proxy/gui/asset-manifest.json +6 -6
- matlab_proxy/gui/index.html +1 -1
- matlab_proxy/gui/static/css/{main.47712126.css → main.da9c4eb8.css} +2 -2
- matlab_proxy/gui/static/css/main.da9c4eb8.css.map +1 -0
- matlab_proxy/gui/static/js/{main.5b5ca2f2.js → main.e07799e7.js} +3 -3
- matlab_proxy/gui/static/js/main.e07799e7.js.map +1 -0
- matlab_proxy/matlab/startup.m +0 -20
- matlab_proxy/settings.py +28 -3
- matlab_proxy/util/__init__.py +101 -1
- matlab_proxy/util/event_loop.py +28 -10
- matlab_proxy/util/mwi/embedded_connector/__init__.py +1 -1
- matlab_proxy/util/mwi/embedded_connector/helpers.py +9 -0
- matlab_proxy/util/mwi/embedded_connector/request.py +51 -21
- matlab_proxy/util/mwi/environment_variables.py +6 -1
- matlab_proxy/util/mwi/exceptions.py +16 -1
- matlab_proxy/util/mwi/validators.py +33 -0
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/METADATA +1 -1
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/RECORD +31 -31
- tests/unit/test_app.py +45 -22
- tests/unit/test_app_state.py +404 -111
- tests/unit/test_constants.py +1 -0
- tests/unit/util/mwi/test_validators.py +30 -1
- tests/unit/util/test_util.py +83 -0
- matlab_proxy/gui/static/css/main.47712126.css.map +0 -1
- matlab_proxy/gui/static/js/main.5b5ca2f2.js.map +0 -1
- /matlab_proxy/gui/static/js/{main.5b5ca2f2.js.LICENSE.txt → main.e07799e7.js.LICENSE.txt} +0 -0
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/LICENSE.md +0 -0
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/WHEEL +0 -0
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/entry_points.txt +0 -0
- {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/top_level.txt +0 -0
matlab_proxy/matlab/startup.m
CHANGED
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
% Copyright 2020-2024 The MathWorks, Inc.
|
|
2
2
|
|
|
3
|
-
% Configure logged in user if possible
|
|
4
|
-
if ~isempty(getenv('MW_LOGIN_USER_ID'))
|
|
5
|
-
user_id = getenv('MW_LOGIN_USER_ID');
|
|
6
|
-
first_name = getenv('MW_LOGIN_FIRST_NAME');
|
|
7
|
-
last_name = getenv('MW_LOGIN_LAST_NAME');
|
|
8
|
-
email_address = getenv('MW_LOGIN_EMAIL_ADDRESS');
|
|
9
|
-
profile_id = getenv('MW_LOGIN_PROFILE_ID');
|
|
10
|
-
display_name = getenv('MW_LOGIN_DISPLAY_NAME');
|
|
11
|
-
|
|
12
|
-
li = com.mathworks.matlab_login.MatlabLogin.isUserLoggedIn(2, 'DESKTOP');
|
|
13
|
-
token = li.getToken();
|
|
14
|
-
login_level = 2;
|
|
15
|
-
remember_me = true;
|
|
16
|
-
li = com.mathworks.matlab_login.MatlabLogin.saveCacheLoginInfo(first_name, ...
|
|
17
|
-
last_name, email_address, user_id, token, profile_id, login_level, ...
|
|
18
|
-
remember_me, email_address, display_name);
|
|
19
|
-
% Clear all local variables from users workspace.
|
|
20
|
-
clear li login_level user_id first_name last_name email_address profile_id display_name token remember_me
|
|
21
|
-
end
|
|
22
|
-
|
|
23
3
|
if (strlength(getenv('MWI_BASE_URL')) > 0)
|
|
24
4
|
connector.internal.setConfig('contextRoot', getenv('MWI_BASE_URL'));
|
|
25
5
|
end
|
matlab_proxy/settings.py
CHANGED
|
@@ -194,6 +194,7 @@ def get_dev_settings(config):
|
|
|
194
194
|
"mwa_login": f"https://login{ws_env_suffix}.mathworks.com",
|
|
195
195
|
"mwi_custom_http_headers": mwi.custom_http_headers.get(),
|
|
196
196
|
"env_config": mwi.validators.validate_env_config(config),
|
|
197
|
+
"integration_name": "MATLAB Desktop",
|
|
197
198
|
"ssl_context": None,
|
|
198
199
|
"mwi_logs_root_dir": get_mwi_logs_root_dir(dev=True),
|
|
199
200
|
"mw_context_tags": get_mw_context_tags(matlab_proxy.get_default_config_name()),
|
|
@@ -209,6 +210,7 @@ def get_dev_settings(config):
|
|
|
209
210
|
),
|
|
210
211
|
"warnings": [],
|
|
211
212
|
"is_xvfb_available": False,
|
|
213
|
+
"mwi_idle_timeout": None,
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
|
|
@@ -301,6 +303,14 @@ def get_server_settings(config_name):
|
|
|
301
303
|
# log file validation check is already done in logger.py
|
|
302
304
|
mwi_log_file = os.getenv(mwi_env.get_env_name_log_file(), None)
|
|
303
305
|
|
|
306
|
+
env_config = mwi.validators.validate_env_config(config_name)
|
|
307
|
+
short_desc = env_config["extension_name_short_description"]
|
|
308
|
+
integration_name = (
|
|
309
|
+
short_desc
|
|
310
|
+
if env_config["extension_name"] == matlab_proxy.get_default_config_name()
|
|
311
|
+
else f"{short_desc} - MATLAB Integration"
|
|
312
|
+
)
|
|
313
|
+
|
|
304
314
|
return {
|
|
305
315
|
"create_xvfb_cmd": create_xvfb_cmd,
|
|
306
316
|
"base_url": mwi.validators.validate_base_url(
|
|
@@ -312,7 +322,8 @@ def get_server_settings(config_name):
|
|
|
312
322
|
"app_port": mwi.validators.validate_app_port_is_free(
|
|
313
323
|
os.getenv(mwi_env.get_env_name_app_port())
|
|
314
324
|
),
|
|
315
|
-
"env_config":
|
|
325
|
+
"env_config": env_config,
|
|
326
|
+
"integration_name": integration_name,
|
|
316
327
|
"mwapikey": str(uuid.uuid4()),
|
|
317
328
|
"matlab_protocol": "https",
|
|
318
329
|
"matlab_config_file": mwi_config_folder / "proxy_app_config.json",
|
|
@@ -334,6 +345,10 @@ def get_server_settings(config_name):
|
|
|
334
345
|
os.getenv(mwi_env.get_env_name_mwi_use_existing_license(), "")
|
|
335
346
|
),
|
|
336
347
|
"ssl_context": _validate_ssl_files_and_get_ssl_context(mwi_config_folder),
|
|
348
|
+
# validate_idle_timeout converts the timeout from minutes to seconds
|
|
349
|
+
"mwi_idle_timeout": mwi.validators.validate_idle_timeout(
|
|
350
|
+
os.getenv(mwi_env.get_env_name_shutdown_on_idle_timeout())
|
|
351
|
+
),
|
|
337
352
|
}
|
|
338
353
|
|
|
339
354
|
|
|
@@ -395,8 +410,10 @@ def get_matlab_settings():
|
|
|
395
410
|
has_custom_code_to_execute = (
|
|
396
411
|
len(os.getenv(mwi_env.get_env_name_custom_matlab_code(), "").strip()) > 0
|
|
397
412
|
)
|
|
398
|
-
|
|
399
|
-
|
|
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;"
|
|
400
417
|
code_to_execute = (
|
|
401
418
|
mp_code_to_execute + custom_code_to_execute
|
|
402
419
|
if has_custom_code_to_execute
|
|
@@ -621,3 +638,11 @@ def generate_new_self_signed_certs(mwi_certs_dir):
|
|
|
621
638
|
cert_file = priv_key_file = None
|
|
622
639
|
|
|
623
640
|
return cert_file, priv_key_file
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def _sanitize_file_path_for_matlab(filepath: str) -> str:
|
|
644
|
+
"""
|
|
645
|
+
Replace single quotes in the filepath with double single quotes to preserve the quote when used in MATLAB code.
|
|
646
|
+
"""
|
|
647
|
+
filepath_with_single_quotes_escaped = filepath.replace("'", "''")
|
|
648
|
+
return filepath_with_single_quotes_escaped
|
matlab_proxy/util/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Copyright 2020-2024 The MathWorks, Inc.
|
|
2
|
-
|
|
3
2
|
import argparse
|
|
3
|
+
import inspect
|
|
4
4
|
import os
|
|
5
5
|
import socket
|
|
6
6
|
import time
|
|
@@ -15,6 +15,11 @@ from matlab_proxy.util.mwi.exceptions import (
|
|
|
15
15
|
UIVisibleFatalError,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
+
from matlab_proxy.util.mwi.exceptions import (
|
|
19
|
+
LockAcquisitionError,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
18
23
|
logger = mwi.logger.get()
|
|
19
24
|
|
|
20
25
|
# Global value to detect whether interrupt signal handler has been triggered or not.
|
|
@@ -276,3 +281,98 @@ def is_valid_path(path: Path):
|
|
|
276
281
|
"""
|
|
277
282
|
path = Path(path)
|
|
278
283
|
return path.is_dir() or path.is_file()
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def get_caller_name() -> str:
|
|
287
|
+
"""Utility function that uses the `inspect` module to access the call stack and returns the name
|
|
288
|
+
of the function that is two levels above in the stack. This is typically the function
|
|
289
|
+
that called the function that invoked `get_caller_name`.
|
|
290
|
+
|
|
291
|
+
Ex: start_matlab() -> set_matlab_state() -> get_caller_name()
|
|
292
|
+
The return value from get_caller_name() would be `start_matlab`
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
str: Name of the parent function.
|
|
296
|
+
"""
|
|
297
|
+
try:
|
|
298
|
+
return inspect.stack()[2][3]
|
|
299
|
+
|
|
300
|
+
except Exception as err:
|
|
301
|
+
logger.error(f"Failed to get caller name with err:{err}")
|
|
302
|
+
stack = inspect.stack()
|
|
303
|
+
return stack[len(stack) - 1][3]
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class TrackingLock:
|
|
307
|
+
"""A class which provides the same features as asyncio.Lock
|
|
308
|
+
and additionally tracks which function acquired the lock.
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
def __init__(self, purpose):
|
|
312
|
+
self._acquired_by = None
|
|
313
|
+
self._lock = asyncio.Lock()
|
|
314
|
+
if not purpose:
|
|
315
|
+
logger.warn("Provide a purpose for this instance of TrackingLock")
|
|
316
|
+
self._purpose = purpose
|
|
317
|
+
|
|
318
|
+
@property
|
|
319
|
+
def acquired_by(self):
|
|
320
|
+
return self._acquired_by
|
|
321
|
+
|
|
322
|
+
@property
|
|
323
|
+
def purpose(self):
|
|
324
|
+
return self._purpose
|
|
325
|
+
|
|
326
|
+
def locked(self):
|
|
327
|
+
return self._lock.locked()
|
|
328
|
+
|
|
329
|
+
async def acquire(self):
|
|
330
|
+
"""Acquires the lock"""
|
|
331
|
+
await self._lock.acquire()
|
|
332
|
+
# Store the current task or function information when the lock is acquired
|
|
333
|
+
self._acquired_by = get_caller_name()
|
|
334
|
+
logger.debug(f"Lock acquired by '{self.acquired_by}()'")
|
|
335
|
+
|
|
336
|
+
async def release(self):
|
|
337
|
+
"""Releases the lock."""
|
|
338
|
+
if self.locked():
|
|
339
|
+
# Clear the owner information when the lock is released
|
|
340
|
+
self._lock.release()
|
|
341
|
+
logger.debug(f"Lock released by '{self.acquired_by}()'")
|
|
342
|
+
self._acquired_by = None
|
|
343
|
+
|
|
344
|
+
else:
|
|
345
|
+
logger.warn(f"Trying to release {self._purpose} lock before acquiring it.")
|
|
346
|
+
|
|
347
|
+
def validate_lock_for_caller(self, caller):
|
|
348
|
+
"""Checks if the specified caller is the current holder of the lock.
|
|
349
|
+
|
|
350
|
+
This method first verifies that the lock is currently held. If it is,
|
|
351
|
+
it then compares the holder's name with the provided caller's name
|
|
352
|
+
to ensure they match.
|
|
353
|
+
|
|
354
|
+
This function should be used by setter methods for verification, before they modify critical sections.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
caller (str): The name of the function to be matched with the lock holder.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
bool: True if the caller currently holds the lock, False otherwise.
|
|
361
|
+
"""
|
|
362
|
+
if not self._lock.locked():
|
|
363
|
+
logger.error(
|
|
364
|
+
LockAcquisitionError(
|
|
365
|
+
f"Lock needs to be acquired by '{caller}()' before modifying {self._purpose}"
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
return False
|
|
369
|
+
|
|
370
|
+
if self._acquired_by != caller:
|
|
371
|
+
logger.error(
|
|
372
|
+
LockAcquisitionError(
|
|
373
|
+
f"Lock was acquired by {self._acquired_by} but {self._purpose} is being modified by {caller}."
|
|
374
|
+
)
|
|
375
|
+
)
|
|
376
|
+
return False
|
|
377
|
+
|
|
378
|
+
return True
|
matlab_proxy/util/event_loop.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# Copyright 2020-
|
|
1
|
+
# Copyright 2020-2024 The MathWorks, Inc.
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Set, Union
|
|
4
|
+
from contextlib import suppress
|
|
2
5
|
|
|
3
6
|
import asyncio
|
|
4
7
|
|
|
5
|
-
from matlab_proxy import util
|
|
6
8
|
from matlab_proxy.util import mwi, system, windows
|
|
7
9
|
|
|
8
10
|
logger = mwi.logger.get()
|
|
@@ -30,16 +32,32 @@ def get_event_loop():
|
|
|
30
32
|
return loop
|
|
31
33
|
|
|
32
34
|
|
|
33
|
-
async def cancel_tasks(tasks):
|
|
35
|
+
async def cancel_tasks(tasks: Union[Dict[str, asyncio.Task], Set[asyncio.Task]]):
|
|
34
36
|
"""Cancels asyncio tasks.
|
|
35
37
|
|
|
36
38
|
Args:
|
|
37
|
-
tasks
|
|
39
|
+
tasks: If a Dict[str, asyncio.Task], contains (task_name, task) as entries.
|
|
40
|
+
If a Set[asyncio.Task], contains a set of asyncio.Task objects.
|
|
41
|
+
"""
|
|
42
|
+
if isinstance(tasks, dict):
|
|
43
|
+
for name, task in list(tasks.items()):
|
|
44
|
+
if task:
|
|
45
|
+
await __cancel_task(task)
|
|
46
|
+
logger.debug(f"{name} task stopped successfully")
|
|
47
|
+
|
|
48
|
+
elif isinstance(tasks, set):
|
|
49
|
+
for task in tasks:
|
|
50
|
+
if task:
|
|
51
|
+
await __cancel_task(task)
|
|
52
|
+
logger.debug(f"Task stopped successfully")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def __cancel_task(task):
|
|
56
|
+
"""Cancels a given asyncio task, suppressing CancelledError.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
task (asyncio.Task): The asyncio task to be cancelled.
|
|
38
60
|
"""
|
|
39
|
-
|
|
40
|
-
logger.debug(f"Calling cancel on task: {task}")
|
|
61
|
+
with suppress(asyncio.CancelledError):
|
|
41
62
|
task.cancel()
|
|
42
|
-
|
|
43
|
-
await task
|
|
44
|
-
except asyncio.CancelledError:
|
|
45
|
-
pass
|
|
63
|
+
await task
|
|
@@ -46,6 +46,15 @@ def get_data_for_ping_request():
|
|
|
46
46
|
return {"messages": {"Ping": [{}]}}
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
def get_data_for_matlab_busy_status_request():
|
|
50
|
+
"""Returns data required to send in the payload for a MATLAB busy/idle status request to the embedded connector
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
dict: Payload data
|
|
54
|
+
"""
|
|
55
|
+
return {"messages": {"GetMatlabStatus": [{}]}}
|
|
56
|
+
|
|
57
|
+
|
|
49
58
|
def get_data_to_eval_mcode(m_code):
|
|
50
59
|
"""Returns the data required to send in the payload for evaluating mcode using eval function to the embedded connector.
|
|
51
60
|
|
|
@@ -12,7 +12,11 @@ from matlab_proxy.util import mwi
|
|
|
12
12
|
|
|
13
13
|
logger = mwi.logger.get()
|
|
14
14
|
|
|
15
|
-
from .helpers import
|
|
15
|
+
from .helpers import (
|
|
16
|
+
get_data_for_ping_request,
|
|
17
|
+
get_data_for_matlab_busy_status_request,
|
|
18
|
+
get_ping_endpoint,
|
|
19
|
+
)
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
async def send_request(url: str, data: dict, method: str, headers: dict = None) -> dict:
|
|
@@ -84,30 +88,56 @@ async def get_state(mwi_server_url, headers=None):
|
|
|
84
88
|
headers=headers,
|
|
85
89
|
)
|
|
86
90
|
|
|
87
|
-
#
|
|
88
|
-
# Tested from R2020b to R2023a
|
|
89
|
-
assert (
|
|
90
|
-
"messages" in resp
|
|
91
|
-
), '"messages" key missing in response from embedded connector'
|
|
92
|
-
assert (
|
|
93
|
-
"PingResponse" in resp["messages"]
|
|
94
|
-
), '"PingResponse" key missing in response from embedded connector'
|
|
95
|
-
assert (
|
|
96
|
-
type(resp["messages"]["PingResponse"]) == list
|
|
97
|
-
), 'Was expecting an array in the "PingResponse" field in response'
|
|
98
|
-
assert (
|
|
99
|
-
len(resp["messages"]["PingResponse"]) == 1
|
|
100
|
-
), 'Was expecting an array of length 1 in the "PingResponse" field in response'
|
|
101
|
-
assert (
|
|
102
|
-
"messageFaults" in resp["messages"]["PingResponse"][0]
|
|
103
|
-
), 'Was expecting "messageFaults" field in response'
|
|
104
|
-
|
|
91
|
+
# Any changes in response from embedded connector would be caught by KeyError
|
|
105
92
|
if not resp["messages"]["PingResponse"][0]["messageFaults"]:
|
|
106
93
|
return "up"
|
|
94
|
+
|
|
95
|
+
except KeyError as key_err:
|
|
96
|
+
logger.error(f"Invalid Key Usage Detected! Check key: {key_err}")
|
|
97
|
+
|
|
107
98
|
except Exception as err:
|
|
108
99
|
logger.debug(
|
|
109
|
-
f"{err}:
|
|
100
|
+
f"{err}: Embbeded connector is currently not responding to ping requests."
|
|
110
101
|
)
|
|
111
|
-
pass
|
|
112
102
|
|
|
113
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
|
|
@@ -167,6 +167,11 @@ def get_env_name_custom_matlab_code():
|
|
|
167
167
|
return "MWI_MATLAB_STARTUP_SCRIPT"
|
|
168
168
|
|
|
169
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
|
+
|
|
170
175
|
class Experimental:
|
|
171
176
|
"""This class houses functions which are undocumented APIs and Environment variables.
|
|
172
177
|
Note: Never add any state to this class. Its only intended for use as an abstraction layer
|
|
@@ -187,7 +192,7 @@ class Experimental:
|
|
|
187
192
|
@staticmethod
|
|
188
193
|
def should_use_mos_html():
|
|
189
194
|
"""Returns true if matlab-proxy should use MOS htmls to load MATLAB"""
|
|
190
|
-
return _is_env_set_to_true("MWI_USE_MOS")
|
|
195
|
+
return _is_env_set_to_true("MWI_USE_MOS")
|
|
191
196
|
|
|
192
197
|
@staticmethod
|
|
193
198
|
def should_use_mre_html():
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2020-2024 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class AppError(Exception):
|
|
@@ -165,6 +165,21 @@ class InvalidTokenError(AppError):
|
|
|
165
165
|
pass
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
class LockAcquisitionError(Exception):
|
|
169
|
+
"""Exception raised when a lock is not properly acquired before modifying a variable.
|
|
170
|
+
|
|
171
|
+
This error is thrown in scenarios where:
|
|
172
|
+
1) A lock must be acquired before modifying a shared resource, but it wasn't.
|
|
173
|
+
2) The lock for a shared resource was acquired by one function, but another function attempts to modify the resource without holding the lock.
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
Exception : Python's inbuilt Exception Class.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
|
|
168
183
|
def log_error(logger, err: Exception):
|
|
169
184
|
"""Logs any error to stdout.
|
|
170
185
|
|
|
@@ -12,6 +12,7 @@ Exceptions are thrown to signal failure.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import errno
|
|
15
|
+
import math
|
|
15
16
|
import os
|
|
16
17
|
import socket
|
|
17
18
|
from pathlib import Path
|
|
@@ -344,3 +345,35 @@ def validate_matlab_root_path(matlab_root: Path, is_custom_matlab_root: bool):
|
|
|
344
345
|
return None
|
|
345
346
|
|
|
346
347
|
return matlab_root
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def validate_idle_timeout(timeout):
|
|
351
|
+
"""Validate if IDLE timeout for matlab-proxy
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
timeout (None | int): IDLE timeout for shutdown of matlab-proxy.
|
|
355
|
+
|
|
356
|
+
Raises:
|
|
357
|
+
ValueError: If a non-numerical value is supplied other than None.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
None | int : The timeout value.
|
|
361
|
+
"""
|
|
362
|
+
if not timeout:
|
|
363
|
+
return timeout
|
|
364
|
+
|
|
365
|
+
try:
|
|
366
|
+
# Convert timeout to seconds
|
|
367
|
+
timeout = math.ceil(float(timeout) * 60)
|
|
368
|
+
|
|
369
|
+
if timeout <= 0:
|
|
370
|
+
raise ValueError
|
|
371
|
+
|
|
372
|
+
logger.info(f"MATLAB IDLE timeout set to {timeout} seconds")
|
|
373
|
+
return timeout
|
|
374
|
+
|
|
375
|
+
except ValueError:
|
|
376
|
+
logger.warn(
|
|
377
|
+
f"Invalid value supplied for {mwi_env.get_env_name_shutdown_on_idle_timeout()}: {timeout}. Continuing without any IDLE timeout."
|
|
378
|
+
)
|
|
379
|
+
return None
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
|
|
2
|
-
matlab_proxy/app.py,sha256=
|
|
3
|
-
matlab_proxy/app_state.py,sha256=
|
|
4
|
-
matlab_proxy/constants.py,sha256
|
|
2
|
+
matlab_proxy/app.py,sha256=6_zql3Uv0gT1pSBDdesZ_FSFqtPWt--YIVyh3cj4d_g,34379
|
|
3
|
+
matlab_proxy/app_state.py,sha256=pt6s3Yy6NV6LB-GxT1Y4cOpeDaTFMm_ItN_qPstDTwE,71296
|
|
4
|
+
matlab_proxy/constants.py,sha256=-gEUNjBATe3_4Cd7CN-VhkEn-iMRfiZ-zdDDD6fM_II,1161
|
|
5
5
|
matlab_proxy/default_configuration.py,sha256=DxQaHzAivzstiPl_nDfxs8SOyP9oaK9v3RP4LtroJl4,843
|
|
6
6
|
matlab_proxy/devel.py,sha256=nR6XPVBUEdQ-RZGtYvX1YHTp8gj9cuw5Hp8ahasMBc8,14310
|
|
7
|
-
matlab_proxy/settings.py,sha256=
|
|
7
|
+
matlab_proxy/settings.py,sha256=Jrk6vkYCKt-cFogkkNpfMcEzZcrDgzfeHqSl6ndgkUA,26722
|
|
8
8
|
matlab_proxy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
matlab_proxy/gui/asset-manifest.json,sha256=
|
|
9
|
+
matlab_proxy/gui/asset-manifest.json,sha256=DvwTnv61wL1g9_YFg4tttJTsaU4QS9atCESSS1tXSAg,3516
|
|
10
10
|
matlab_proxy/gui/favicon.ico,sha256=7w7Ki1uQP2Rgwc64dOV4-NrTu97I3WsZw8OvRSoY1A0,130876
|
|
11
|
-
matlab_proxy/gui/index.html,sha256=
|
|
11
|
+
matlab_proxy/gui/index.html,sha256=QfpshVMgl83FzcW82qdNIaGRp-KJ0oIIErk0wDK_Gps,637
|
|
12
12
|
matlab_proxy/gui/manifest.json,sha256=NwDbrALM5auYyj2bbEf4aGwAUDqNl1FzMFQpPiG2Ty4,286
|
|
13
13
|
matlab_proxy/gui/robots.txt,sha256=kNJLw79pisHhc3OVAimMzKcq3x9WT6sF9IS4xI0crdI,67
|
|
14
14
|
matlab_proxy/gui/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
matlab_proxy/gui/static/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
matlab_proxy/gui/static/css/main.
|
|
17
|
-
matlab_proxy/gui/static/css/main.
|
|
16
|
+
matlab_proxy/gui/static/css/main.da9c4eb8.css,sha256=etg2mMerqvNiYKBJgve5vBUc-X8ZnnCVnf5gc-DMaPA,274453
|
|
17
|
+
matlab_proxy/gui/static/css/main.da9c4eb8.css.map,sha256=favITMsubUPvF7E0vWcdc2RXJ9Pj5ljIWdPuhSBfDVU,351326
|
|
18
18
|
matlab_proxy/gui/static/js/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
matlab_proxy/gui/static/js/main.
|
|
20
|
-
matlab_proxy/gui/static/js/main.
|
|
21
|
-
matlab_proxy/gui/static/js/main.
|
|
19
|
+
matlab_proxy/gui/static/js/main.e07799e7.js,sha256=rtgmv7rYVVOVheycw3zNBjIyKv63qeTRgZ4zmO4HxCs,298414
|
|
20
|
+
matlab_proxy/gui/static/js/main.e07799e7.js.LICENSE.txt,sha256=3cj3DrwM51esz1ogL9VVU1ZyXyXJ6u-Ec2CI9CCcI_A,1689
|
|
21
|
+
matlab_proxy/gui/static/js/main.e07799e7.js.map,sha256=nCto0v-cMAs0t2YmSz2UqwJ3PlWgoW6aLRNYo67Nie0,955674
|
|
22
22
|
matlab_proxy/gui/static/media/MATLAB-env-blur.4fc94edbc82d3184e5cb.png,sha256=QpmQTLDvBu2-b7ev83Rvpt0Q72R6wdQGkuJMPPpjv7M,220290
|
|
23
23
|
matlab_proxy/gui/static/media/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
matlab_proxy/gui/static/media/arrow.0c2968b90bd9a64c8c3f.svg,sha256=XtmvDWzGZnwCZm08TKBnqt5hc1wphJnNupG0Fx_faAY,327
|
|
@@ -53,9 +53,9 @@ matlab_proxy/gui/static/media/trigger-error.3f1c4ef23ab8f3e60b0e.svg,sha256=3zzT
|
|
|
53
53
|
matlab_proxy/gui/static/media/trigger-ok.7b9c238be42f685c4fa7.svg,sha256=mD-7N9cc4ARdMBFcplnogJv6nA4Yh3jQuYbZDUi18LU,4997
|
|
54
54
|
matlab_proxy/icons/matlab.svg,sha256=xh5uYebQd8I-ISvenjU9A-PkClzW_lU9wvm3doXOFKM,13366
|
|
55
55
|
matlab_proxy/matlab/evaluateUserMatlabCode.m,sha256=R8w6nPdGtadR4UUFJaspcrGQL7cJwUItdrfc531w3bM,2420
|
|
56
|
-
matlab_proxy/matlab/startup.m,sha256=
|
|
57
|
-
matlab_proxy/util/__init__.py,sha256=
|
|
58
|
-
matlab_proxy/util/event_loop.py,sha256=
|
|
56
|
+
matlab_proxy/matlab/startup.m,sha256=Rgb1Y3F2pFgByKAaXxWWcYOA2594D7V2HXuyuVmGYjs,653
|
|
57
|
+
matlab_proxy/util/__init__.py,sha256=CoH6sfgrQ1phhO1FXeyQwTjtl7PPgeZOCGNrkyGv-5o,11711
|
|
58
|
+
matlab_proxy/util/event_loop.py,sha256=sX_0tKlirCY5ImLxkss_XO4Ksj65u6JHtwMj25oGL94,1816
|
|
59
59
|
matlab_proxy/util/list_servers.py,sha256=M93coVZjyQCdIvCCxsNOU_XDWNjBSysOJ5tWXaTjP8Y,1369
|
|
60
60
|
matlab_proxy/util/mw.py,sha256=dLGSdfcTZiwKR1MMZA-39o-8na13IEPZOGBqcaHmKVI,11086
|
|
61
61
|
matlab_proxy/util/system.py,sha256=XoT3Rv5MwPkdfhk2oMvUwxxlzZmADMlxzi9IRQyGgbA,1692
|
|
@@ -63,14 +63,14 @@ matlab_proxy/util/windows.py,sha256=J5O-wihOxEex43_AzwvFylNlN4hcZdO6KD5cpLv1FX8,
|
|
|
63
63
|
matlab_proxy/util/mwi/__init__.py,sha256=zI-X1lafr8H3j17PyA0oSZ0q5nINfK-WDA7VmJKmSAQ,158
|
|
64
64
|
matlab_proxy/util/mwi/custom_http_headers.py,sha256=kfDjSnEXEVzoF2pZuEn76LKayeD2WKoQEDu2Y9EMOAo,7154
|
|
65
65
|
matlab_proxy/util/mwi/download.py,sha256=-GJj3yOsL4vF_9baqRXkgBI-vu_OwjZMQVkJXFS8GMc,4965
|
|
66
|
-
matlab_proxy/util/mwi/environment_variables.py,sha256=
|
|
67
|
-
matlab_proxy/util/mwi/exceptions.py,sha256=
|
|
66
|
+
matlab_proxy/util/mwi/environment_variables.py,sha256=sOfmL8PjQONgkJdegdotLbsqHsWJDsjS7kak0TJtVKU,7441
|
|
67
|
+
matlab_proxy/util/mwi/exceptions.py,sha256=3jklFU6br2_pSSsATCRDY3A5fTzk6ekJ4M69sunwxBk,5114
|
|
68
68
|
matlab_proxy/util/mwi/logger.py,sha256=e7wTPclrtJ-aX5mPk_pUJMX7-1QD_snGBW1P2ks-ETE,3311
|
|
69
69
|
matlab_proxy/util/mwi/token_auth.py,sha256=UbIWqo7qADaZdijFvorLYsZbxzaB8TycGP8nk305ru0,9997
|
|
70
|
-
matlab_proxy/util/mwi/validators.py,sha256=
|
|
71
|
-
matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=
|
|
72
|
-
matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=
|
|
73
|
-
matlab_proxy/util/mwi/embedded_connector/request.py,sha256=-
|
|
70
|
+
matlab_proxy/util/mwi/validators.py,sha256=br-22Gyef_vxVSSH2Qkb97Nfph9sfl7fyhQ8-LWkBP4,12600
|
|
71
|
+
matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=Vfl2hNC7V1IwoK9_wrwfENs4BC8P-Mvvqh4BNGi2n48,119
|
|
72
|
+
matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=aOn-AvcDy6jBQJIffiv_agIa4UVldAIl3--QnDpXWDM,3656
|
|
73
|
+
matlab_proxy/util/mwi/embedded_connector/request.py,sha256=-IzTDjy3qViHfLJpK3OnFtEyV7dgwJKPQAfav9lqILc,4317
|
|
74
74
|
tests/integration/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
75
75
|
tests/integration/integration_tests_with_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
|
|
76
76
|
tests/integration/integration_tests_with_license/conftest.py,sha256=sCaIXB8d4vf05C7JWSVA7g5gnPjbpRq3dftuBpWyp1s,1599
|
|
@@ -83,30 +83,30 @@ tests/integration/utils/integration_tests_utils.py,sha256=IbJ9CedFHiz3k85FBY-8Gw
|
|
|
83
83
|
tests/integration/utils/licensing.py,sha256=rEBjvMXO8R3mL6KnePu2lojmOsjD4GXl9frf9N0Wacs,4842
|
|
84
84
|
tests/unit/__init__.py,sha256=KfwQxxM5a1kMRtNbhz8tb7YfHp8e2d0tNLB55wYvDS8,37
|
|
85
85
|
tests/unit/conftest.py,sha256=Hfxq3h8IZuLJkRMh5jdEFiq78CIAdKvm-6KryRDZ0FY,1918
|
|
86
|
-
tests/unit/test_app.py,sha256=
|
|
87
|
-
tests/unit/test_app_state.py,sha256=
|
|
88
|
-
tests/unit/test_constants.py,sha256=
|
|
86
|
+
tests/unit/test_app.py,sha256=LkIqION-F_4dDpbT0VXzdL_ue-1HGXhPRP9-AprcRKY,38443
|
|
87
|
+
tests/unit/test_app_state.py,sha256=ZtM79HAe5W6pVVWV-NICjDJBlmuxJ4NnZn-urGGtH-E,33429
|
|
88
|
+
tests/unit/test_constants.py,sha256=2nXxTmDP8utr8krsfZ4c_Bh4_mWPcDO5uI8MXeq4Usg,158
|
|
89
89
|
tests/unit/test_ddux.py,sha256=a2J2iM8j_nnfJVuMI38p5AjwrRdoMj3N88gFgS2I4hg,713
|
|
90
90
|
tests/unit/test_devel.py,sha256=A-1iVhSSwmywaW65QIRcUS2Fk7nJxceCcCm7CJtNdEc,7982
|
|
91
91
|
tests/unit/test_non_dev_mode.py,sha256=0v27y27SLOWvw6jf_GhLLNg-RMsZS_OyGAnqoQYPpSA,5515
|
|
92
92
|
tests/unit/test_settings.py,sha256=eBlV-ME_O8oLoOjJqqYTDTXJs-0smnM0oIMwHZEjUbo,17727
|
|
93
93
|
tests/unit/util/__init__.py,sha256=GInSQBb2SoVD5LZfmSCQa9-UZJT_UP-jNfrojkgCybU,87
|
|
94
94
|
tests/unit/util/test_mw.py,sha256=YC4mjn6G6_XuHELt8uW9F6g2K0_fWtQl1R0kWFvWbAo,18565
|
|
95
|
-
tests/unit/util/test_util.py,sha256=
|
|
95
|
+
tests/unit/util/test_util.py,sha256=gecUFSVIg4a9s3Ljl0A7eSSY5jN4vH668CbjnTpi198,7431
|
|
96
96
|
tests/unit/util/mwi/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
|
|
97
97
|
tests/unit/util/mwi/test_custom_http_headers.py,sha256=UfrhclS0j6WhShtg1ki2oF1kK8JqRC29uevH4tuDqF4,11182
|
|
98
98
|
tests/unit/util/mwi/test_download.py,sha256=jYwPJFYGrPKqnkIJW42XYSe1fowmzChAkOx0k0xVldo,4779
|
|
99
99
|
tests/unit/util/mwi/test_logger.py,sha256=zWImNitMYKPJunXWJjEDEtCEKwBz615PC844ZLwoxIg,1845
|
|
100
100
|
tests/unit/util/mwi/test_token_auth.py,sha256=-eBsaQ5JC7pyd9PXt48Rqs4cWjg6I-eOkp_gFVEwYhk,10538
|
|
101
|
-
tests/unit/util/mwi/test_validators.py,sha256=
|
|
101
|
+
tests/unit/util/mwi/test_validators.py,sha256=rzSmifQdPWZ5ZjecShBpC_RYL55_smCsG248h2JzUDU,11467
|
|
102
102
|
tests/unit/util/mwi/embedded_connector/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
|
|
103
103
|
tests/unit/util/mwi/embedded_connector/test_helpers.py,sha256=vYTWNUTuDeaygo16JGMTvWeI_CLOnvPkwNJmLndvJhE,890
|
|
104
104
|
tests/unit/util/mwi/embedded_connector/test_request.py,sha256=PR-jddnXDEiip-lD7A_QSvRwEkwo3eQ8owZlk-r9vnk,1867
|
|
105
105
|
tests/utils/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
106
106
|
tests/utils/logging_util.py,sha256=VBy_NRvwau3C_CVTBjK5RMROrQimnJYHO2U0aKSZiRw,2234
|
|
107
|
-
matlab_proxy-0.
|
|
108
|
-
matlab_proxy-0.
|
|
109
|
-
matlab_proxy-0.
|
|
110
|
-
matlab_proxy-0.
|
|
111
|
-
matlab_proxy-0.
|
|
112
|
-
matlab_proxy-0.
|
|
107
|
+
matlab_proxy-0.19.0.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
|
|
108
|
+
matlab_proxy-0.19.0.dist-info/METADATA,sha256=UPcQ8G3Z3NGsFcIrXpEhDj-RVJMAIDYQSNZxCFWf4HY,10177
|
|
109
|
+
matlab_proxy-0.19.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
110
|
+
matlab_proxy-0.19.0.dist-info/entry_points.txt,sha256=DbBLYgnRt8UGiOpd0zHigRTyyMdZYhMdvCvSYP7wPN0,244
|
|
111
|
+
matlab_proxy-0.19.0.dist-info/top_level.txt,sha256=9uVTjsUCAS4TwsxueTBxrBg3PdBiTSsYowAkHPv9VY0,19
|
|
112
|
+
matlab_proxy-0.19.0.dist-info/RECORD,,
|