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.

Files changed (33) hide show
  1. matlab_proxy/app.py +54 -43
  2. matlab_proxy/app_state.py +370 -155
  3. matlab_proxy/constants.py +3 -0
  4. matlab_proxy/gui/asset-manifest.json +6 -6
  5. matlab_proxy/gui/index.html +1 -1
  6. matlab_proxy/gui/static/css/{main.47712126.css → main.da9c4eb8.css} +2 -2
  7. matlab_proxy/gui/static/css/main.da9c4eb8.css.map +1 -0
  8. matlab_proxy/gui/static/js/{main.5b5ca2f2.js → main.e07799e7.js} +3 -3
  9. matlab_proxy/gui/static/js/main.e07799e7.js.map +1 -0
  10. matlab_proxy/matlab/startup.m +0 -20
  11. matlab_proxy/settings.py +28 -3
  12. matlab_proxy/util/__init__.py +101 -1
  13. matlab_proxy/util/event_loop.py +28 -10
  14. matlab_proxy/util/mwi/embedded_connector/__init__.py +1 -1
  15. matlab_proxy/util/mwi/embedded_connector/helpers.py +9 -0
  16. matlab_proxy/util/mwi/embedded_connector/request.py +51 -21
  17. matlab_proxy/util/mwi/environment_variables.py +6 -1
  18. matlab_proxy/util/mwi/exceptions.py +16 -1
  19. matlab_proxy/util/mwi/validators.py +33 -0
  20. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/METADATA +1 -1
  21. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/RECORD +31 -31
  22. tests/unit/test_app.py +45 -22
  23. tests/unit/test_app_state.py +404 -111
  24. tests/unit/test_constants.py +1 -0
  25. tests/unit/util/mwi/test_validators.py +30 -1
  26. tests/unit/util/test_util.py +83 -0
  27. matlab_proxy/gui/static/css/main.47712126.css.map +0 -1
  28. matlab_proxy/gui/static/js/main.5b5ca2f2.js.map +0 -1
  29. /matlab_proxy/gui/static/js/{main.5b5ca2f2.js.LICENSE.txt → main.e07799e7.js.LICENSE.txt} +0 -0
  30. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/LICENSE.md +0 -0
  31. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/WHEEL +0 -0
  32. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/entry_points.txt +0 -0
  33. {matlab_proxy-0.18.1.dist-info → matlab_proxy-0.19.0.dist-info}/top_level.txt +0 -0
@@ -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": mwi.validators.validate_env_config(config_name),
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
- mp_code_to_execute = f"try; run('{matlab_startup_file}'); catch MATLABProxyInitializationError; disp(MATLABProxyInitializationError.message); end;"
399
- custom_code_to_execute = f"try; run('{matlab_code_file}'); catch MATLABCustomStartupCodeError; disp(MATLABCustomStartupCodeError.message); end;"
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
@@ -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
@@ -1,8 +1,10 @@
1
- # Copyright 2020-2022 The MathWorks, Inc.
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 (asyncio.Task): Asyncio task
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
- for task in tasks:
40
- logger.debug(f"Calling cancel on task: {task}")
61
+ with suppress(asyncio.CancelledError):
41
62
  task.cancel()
42
- try:
43
- await task
44
- except asyncio.CancelledError:
45
- pass
63
+ await task
@@ -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
@@ -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 get_data_for_ping_request, get_ping_endpoint
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
- # Additional assert statements to catch any changes in response from embedded connector
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}: Embedded connector is currently not responding to ping requests."
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") or Experimental.is_simulink_enabled()
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 (c) 2020-2023 The MathWorks, Inc.
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: matlab-proxy
3
- Version: 0.18.1
3
+ Version: 0.19.0
4
4
  Summary: Python® package enables you to launch MATLAB® and access it from a web browser.
5
5
  Home-page: https://github.com/mathworks/matlab-proxy/
6
6
  Author: The MathWorks, Inc.
@@ -1,24 +1,24 @@
1
1
  matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
2
- matlab_proxy/app.py,sha256=ri2Dm3G3uVmIhoEV01awazsO4t3Z92LEwin657bq8bw,34538
3
- matlab_proxy/app_state.py,sha256=i5AVaNroFSld4Y36BNil5lwS0PNrHnceYq7swXY5AI4,60502
4
- matlab_proxy/constants.py,sha256=CrbIA098b5LMsqxY7nbap0_tqA2tIrIckGAffTgIkrA,1039
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=I4nvFZzACKx-JBlAFCFWHA60gg66bR4hrXj1f5awfbA,25616
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=XqmLvi3DDOGSbBxNZwjuaNJXoYjZiG2HasxvZnEzPEo,3516
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=lWKKMXjAyOc-vk6t4rasj49sa2UgXAAlMdWYCd5V8N8,637
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.47712126.css,sha256=OT5ccyC0a6fVg956C-8b6uDVbZZVgcpXbHjdO6v4ZBI,274313
17
- matlab_proxy/gui/static/css/main.47712126.css.map,sha256=RdfmXfQvzvvh4XZuDWShm8CD8pA2Gb2K6MtMzrgJyKM,350495
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.5b5ca2f2.js,sha256=XvoCZpW63pLcHvS9meZxIId_yQPC3w5SuGIij5VwOEc,294436
20
- matlab_proxy/gui/static/js/main.5b5ca2f2.js.LICENSE.txt,sha256=3cj3DrwM51esz1ogL9VVU1ZyXyXJ6u-Ec2CI9CCcI_A,1689
21
- matlab_proxy/gui/static/js/main.5b5ca2f2.js.map,sha256=mCDweY7BuQ4Ld5c6Z521rjPGrIlIzG2b_DjxsW_eo6M,938339
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=1hIvfWgBDcvM3wW__X2yaQ6cBwKjdh5eO0zycbJB78k,1555
57
- matlab_proxy/util/__init__.py,sha256=rhBsXJT-5v67FuJ9Rz23yDT7afYfwrS5y_oMQSTbCwg,8456
58
- matlab_proxy/util/event_loop.py,sha256=Zqd282jlvPHHyc4kg8IjIzlzh9zLM_SAc5xjqUOrm04,1144
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=SC5pMCs2EVWd9NrvA8yYbCOm998SXDhQCIG1h8Ilysc,7309
67
- matlab_proxy/util/mwi/exceptions.py,sha256=93HrHbOq24KI4Md2el23XN01wIqVShEK29Pbt2V0Jr8,4628
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=QEaP0N6U8BF4MglxrkM1phK0lWNiWBK7JdJbcfFRACY,11765
71
- matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=SVSckEJ4zQQ2KkNPT_un8ndMAImcMOTrai7ShAbmFY4,114
72
- matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=p6TedefbvhlZT64IMwFjrb0panWCXf-T3XPoztDbxM0,3391
73
- matlab_proxy/util/mwi/embedded_connector/request.py,sha256=-6DL9K8JWjX5u5XVOEGaqBUIwQ-oCVW30-VP3qk_rzw,3730
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=xiiEQu1iNK0h3Yuwn3c-hgvNhC1EXKFgTbE_7U3mSrs,37731
87
- tests/unit/test_app_state.py,sha256=qD2I7qfUwME_M8lCMsg62Kmky5xdCBav3r3em39Zkt0,22906
88
- tests/unit/test_constants.py,sha256=ieDKc7bL8zWsd_D4dv2n8iftXr2h-bkS5p6zVan0BtQ,125
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=vqTPgmaKDWhVBRnCKtCNg-OtyR5bP8jeH9DnpcbfVTk,5141
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=YeOP0-T7SFNeiC7JIQj7cV4ja3d6PhswsTz27IEgJHQ,10852
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.18.1.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
108
- matlab_proxy-0.18.1.dist-info/METADATA,sha256=Q5A3PKIyRDzKYk96M5XLsxeh6vHUIl4mDubWPAQvock,10177
109
- matlab_proxy-0.18.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
110
- matlab_proxy-0.18.1.dist-info/entry_points.txt,sha256=DbBLYgnRt8UGiOpd0zHigRTyyMdZYhMdvCvSYP7wPN0,244
111
- matlab_proxy-0.18.1.dist-info/top_level.txt,sha256=9uVTjsUCAS4TwsxueTBxrBg3PdBiTSsYowAkHPv9VY0,19
112
- matlab_proxy-0.18.1.dist-info/RECORD,,
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,,