matlab-proxy 0.27.1__py3-none-any.whl → 0.27.3__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 +3 -3
- matlab_proxy/app_state.py +19 -23
- matlab_proxy/settings.py +2 -3
- matlab_proxy/util/__init__.py +23 -42
- matlab_proxy/util/list_servers.py +70 -25
- matlab_proxy/util/mwi/environment_variables.py +10 -0
- matlab_proxy/util/mwi/logger.py +115 -30
- matlab_proxy/util/mwi/validators.py +1 -1
- {matlab_proxy-0.27.1.dist-info → matlab_proxy-0.27.3.dist-info}/METADATA +2 -1
- {matlab_proxy-0.27.1.dist-info → matlab_proxy-0.27.3.dist-info}/RECORD +13 -13
- {matlab_proxy-0.27.1.dist-info → matlab_proxy-0.27.3.dist-info}/WHEEL +0 -0
- {matlab_proxy-0.27.1.dist-info → matlab_proxy-0.27.3.dist-info}/entry_points.txt +0 -0
- {matlab_proxy-0.27.1.dist-info → matlab_proxy-0.27.3.dist-info}/licenses/LICENSE.md +0 -0
matlab_proxy/app.py
CHANGED
|
@@ -996,7 +996,7 @@ def configure_no_proxy_in_env():
|
|
|
996
996
|
os.environ["no_proxy"] = ",".join(
|
|
997
997
|
set(existing_no_proxy_env + no_proxy_whitelist)
|
|
998
998
|
)
|
|
999
|
-
logger.
|
|
999
|
+
logger.debug(f"Setting no_proxy to: {os.environ.get('no_proxy')}")
|
|
1000
1000
|
|
|
1001
1001
|
|
|
1002
1002
|
def create_and_start_app(config_name):
|
|
@@ -1053,12 +1053,12 @@ def print_version_and_exit():
|
|
|
1053
1053
|
|
|
1054
1054
|
def main():
|
|
1055
1055
|
"""Starting point of the integration. Creates the web app and runs indefinitely."""
|
|
1056
|
-
if util.
|
|
1056
|
+
if util.parse_main_cli_args()["version"]:
|
|
1057
1057
|
print_version_and_exit()
|
|
1058
1058
|
|
|
1059
1059
|
# The integration needs to be called with --config flag.
|
|
1060
1060
|
# Parse the passed cli arguments.
|
|
1061
|
-
desired_configuration_name = util.
|
|
1061
|
+
desired_configuration_name = util.parse_main_cli_args()["config"]
|
|
1062
1062
|
|
|
1063
1063
|
create_and_start_app(config_name=desired_configuration_name)
|
|
1064
1064
|
|
matlab_proxy/app_state.py
CHANGED
|
@@ -875,15 +875,8 @@ class AppState:
|
|
|
875
875
|
user_code_output_file
|
|
876
876
|
)
|
|
877
877
|
logger.info(
|
|
878
|
-
|
|
879
|
-
boundary_filler="*",
|
|
880
|
-
text_arr=[
|
|
881
|
-
f"When MATLAB starts, you can see the output for your startup code at:",
|
|
882
|
-
f"{self.matlab_session_files.get('startup_code_output_file', ' ')}",
|
|
883
|
-
],
|
|
884
|
-
)
|
|
878
|
+
f"The results of executing MWI_MATLAB_STARTUP_SCRIPT are stored at: {user_code_output_file} "
|
|
885
879
|
)
|
|
886
|
-
|
|
887
880
|
return
|
|
888
881
|
|
|
889
882
|
def create_server_info_file(self):
|
|
@@ -909,16 +902,16 @@ class AppState:
|
|
|
909
902
|
|
|
910
903
|
# By default mwi_server_url usually points to 0.0.0.0 as the hostname, but this does not work well
|
|
911
904
|
# on some browsers. Specifically on Safari (MacOS)
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
)
|
|
905
|
+
server_url = (
|
|
906
|
+
self.settings["mwi_server_url"].replace("0.0.0.0", "localhost")
|
|
907
|
+
+ mwi_auth_token_str
|
|
908
|
+
)
|
|
909
|
+
|
|
910
|
+
mwi.logger.log_startup_info(
|
|
911
|
+
title=f"matlab-proxy-app running on {self.settings['app_port']}",
|
|
912
|
+
matlab_url=server_url,
|
|
921
913
|
)
|
|
914
|
+
logger.info(f"MATLAB Root: {self.settings['matlab_path']}")
|
|
922
915
|
|
|
923
916
|
def clean_up_mwi_server_session(self):
|
|
924
917
|
# Clean up mwi_server_session_files
|
|
@@ -965,10 +958,11 @@ class AppState:
|
|
|
965
958
|
matlab_env["MLM_LICENSE_FILE"] = self.licensing["conn_str"]
|
|
966
959
|
|
|
967
960
|
# Env setup related to MATLAB
|
|
968
|
-
|
|
969
|
-
matlab_env["
|
|
970
|
-
matlab_env["
|
|
971
|
-
|
|
961
|
+
## Update the values only if it does not already exist in the environment
|
|
962
|
+
matlab_env["MW_CRASH_MODE"] = matlab_env.get("MW_CRASH_MODE", "native")
|
|
963
|
+
matlab_env["MATLAB_WORKER_CONFIG_ENABLE_LOCAL_PARCLUSTER"] = matlab_env.get(
|
|
964
|
+
"MATLAB_WORKER_CONFIG_ENABLE_LOCAL_PARCLUSTER", "true"
|
|
965
|
+
)
|
|
972
966
|
matlab_env["MW_DOCROOT"] = os.path.join("ui", "webgui", "src")
|
|
973
967
|
matlab_env["MWAPIKEY"] = self.settings["mwapikey"]
|
|
974
968
|
|
|
@@ -1003,7 +997,7 @@ class AppState:
|
|
|
1003
997
|
|
|
1004
998
|
# Set MW_CONNECTOR_CONTEXT_ROOT
|
|
1005
999
|
matlab_env["MW_CONNECTOR_CONTEXT_ROOT"] = self.settings.get("base_url", "/")
|
|
1006
|
-
logger.
|
|
1000
|
+
logger.debug(
|
|
1007
1001
|
f"MW_CONNECTOR_CONTEXT_ROOT is set to: {matlab_env['MW_CONNECTOR_CONTEXT_ROOT']}"
|
|
1008
1002
|
)
|
|
1009
1003
|
|
|
@@ -1315,6 +1309,8 @@ class AppState:
|
|
|
1315
1309
|
# to MATLAB state by other functions/tasks until the lock is released, ensuring consistency. It's released early only in case of exceptions.
|
|
1316
1310
|
await self.matlab_state_updater_lock.acquire()
|
|
1317
1311
|
self.set_matlab_state("starting")
|
|
1312
|
+
logger.info(f"Starting MATLAB...")
|
|
1313
|
+
|
|
1318
1314
|
# Clear MATLAB errors and logging
|
|
1319
1315
|
self.error = None
|
|
1320
1316
|
self.logs["matlab"].clear()
|
|
@@ -1534,7 +1530,7 @@ class AppState:
|
|
|
1534
1530
|
except:
|
|
1535
1531
|
pass
|
|
1536
1532
|
|
|
1537
|
-
logger.
|
|
1533
|
+
logger.debug("Stopped (any running) MATLAB process.")
|
|
1538
1534
|
|
|
1539
1535
|
# Terminating Xvfb
|
|
1540
1536
|
if system.is_posix():
|
matlab_proxy/settings.py
CHANGED
|
@@ -53,7 +53,7 @@ def get_process_startup_timeout():
|
|
|
53
53
|
)
|
|
54
54
|
return constants.DEFAULT_PROCESS_START_TIMEOUT
|
|
55
55
|
|
|
56
|
-
logger.
|
|
56
|
+
logger.debug(
|
|
57
57
|
f"Using {constants.DEFAULT_PROCESS_START_TIMEOUT} seconds as the default timeout value"
|
|
58
58
|
)
|
|
59
59
|
|
|
@@ -94,7 +94,7 @@ def get_matlab_executable_and_root_path():
|
|
|
94
94
|
|
|
95
95
|
if matlab_executable_path:
|
|
96
96
|
matlab_root_path = Path(matlab_executable_path).resolve().parent.parent
|
|
97
|
-
logger.
|
|
97
|
+
logger.debug(f"MATLAB root folder: {matlab_root_path}")
|
|
98
98
|
matlab_root_path = mwi.validators.validate_matlab_root_path(
|
|
99
99
|
matlab_root_path, is_custom_matlab_root=False
|
|
100
100
|
)
|
|
@@ -698,7 +698,6 @@ def _get_matlab_cmd(matlab_executable_path, code_to_execute, nlm_conn_str):
|
|
|
698
698
|
"-nosplash",
|
|
699
699
|
*flag_to_hide_desktop,
|
|
700
700
|
"-softwareopengl",
|
|
701
|
-
# " v=mvm ",
|
|
702
701
|
*matlab_lic_mode,
|
|
703
702
|
"-externalUI",
|
|
704
703
|
profile_matlab_startup,
|
matlab_proxy/util/__init__.py
CHANGED
|
@@ -26,7 +26,7 @@ logger = mwi.logger.get()
|
|
|
26
26
|
interrupt_signal_caught = False
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
def
|
|
29
|
+
def parse_main_cli_args():
|
|
30
30
|
"""Parses CLI arguments passed to the main() function.
|
|
31
31
|
|
|
32
32
|
Returns:
|
|
@@ -56,6 +56,28 @@ def parse_cli_args():
|
|
|
56
56
|
return parsed_args
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
def parse_list_cli_args():
|
|
60
|
+
"""Parses CLI arguments passed to the matlab-proxy-app-list-servers entrypoint.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
dict: Containing the parsed arguments
|
|
64
|
+
"""
|
|
65
|
+
# Parse the --config flag provided to the console script executable.
|
|
66
|
+
parsed_args = {}
|
|
67
|
+
parser = argparse.ArgumentParser()
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"-q",
|
|
70
|
+
"--quiet",
|
|
71
|
+
help="Return the server list without any additional text.",
|
|
72
|
+
action="store_true",
|
|
73
|
+
)
|
|
74
|
+
args = parser.parse_args()
|
|
75
|
+
|
|
76
|
+
parsed_args["quiet"] = args.quiet
|
|
77
|
+
|
|
78
|
+
return parsed_args
|
|
79
|
+
|
|
80
|
+
|
|
59
81
|
def prepare_site(app, runner):
|
|
60
82
|
"""Prepares to launch a TCPSite. If MWI_APP_PORT env variable is set,
|
|
61
83
|
it will setup a site to launch on that port, else will launch on a random available port.
|
|
@@ -148,47 +170,6 @@ def add_signal_handlers(loop):
|
|
|
148
170
|
return loop
|
|
149
171
|
|
|
150
172
|
|
|
151
|
-
def prettify(boundary_filler=" ", text_arr=[]):
|
|
152
|
-
"""Prettify array of strings with borders for stdout
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
boundary_filler (str, optional): Upper and lower border filler for text. Defaults to " ".
|
|
156
|
-
text_arr (list, optional):The text array to prettify. Each element will be added to a newline. Defaults to [].
|
|
157
|
-
|
|
158
|
-
Returns:
|
|
159
|
-
[str]: Prettified String
|
|
160
|
-
"""
|
|
161
|
-
|
|
162
|
-
import sys
|
|
163
|
-
|
|
164
|
-
if not sys.stdout.isatty():
|
|
165
|
-
return (
|
|
166
|
-
"\n============================\n"
|
|
167
|
-
+ "\n".join(text_arr)
|
|
168
|
-
+ "\n============================\n"
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
size = os.get_terminal_size()
|
|
172
|
-
cols, _ = size.columns, size.lines
|
|
173
|
-
|
|
174
|
-
if any(len(text) > cols for text in text_arr):
|
|
175
|
-
result = ""
|
|
176
|
-
for text in text_arr:
|
|
177
|
-
result += text + "\n"
|
|
178
|
-
return result
|
|
179
|
-
|
|
180
|
-
upper = "\n" + "".ljust(cols, boundary_filler) + "\n" if len(text_arr) > 0 else ""
|
|
181
|
-
lower = "".ljust(cols, boundary_filler) if len(text_arr) > 0 else ""
|
|
182
|
-
|
|
183
|
-
content = ""
|
|
184
|
-
for text in text_arr:
|
|
185
|
-
content += text.center(cols) + "\n"
|
|
186
|
-
|
|
187
|
-
result = upper + content + lower
|
|
188
|
-
|
|
189
|
-
return result
|
|
190
|
-
|
|
191
|
-
|
|
192
173
|
def get_child_processes(parent_process, max_attempts=10, sleep_interval=1):
|
|
193
174
|
"""Get list of child processes from a parent process.
|
|
194
175
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2020-
|
|
1
|
+
# Copyright (c) 2020-2025 The MathWorks, Inc.
|
|
2
2
|
# Script to print information about all running matlab-proxy servers for current user on current machine.
|
|
3
3
|
|
|
4
4
|
import glob
|
|
@@ -7,6 +7,66 @@ import os
|
|
|
7
7
|
import matlab_proxy.settings as mwi_settings
|
|
8
8
|
import matlab_proxy.util as mwi_util
|
|
9
9
|
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.table import Table
|
|
13
|
+
|
|
14
|
+
__NO_SERVERS_MSG = "No MATLAB-PROXY Servers are currently running."
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _extract_version_and_session(title):
|
|
18
|
+
"""Extracts session name and MATLAB version from the title."""
|
|
19
|
+
parts = title.split("-")
|
|
20
|
+
if len(parts) < 2:
|
|
21
|
+
return title.replace("MATLAB ", ""), ""
|
|
22
|
+
session_name = parts[0].strip()
|
|
23
|
+
matlab_version = parts[1].strip().replace("MATLAB ", "")
|
|
24
|
+
return matlab_version, session_name
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _get_server_info(server):
|
|
28
|
+
"""Helper function to parse info from server file."""
|
|
29
|
+
with open(server) as f:
|
|
30
|
+
# Assumes that the server file contains the address on the first line,
|
|
31
|
+
# the browser_title on the second line, and the timestamp is derived from the file's last modified time.
|
|
32
|
+
address = f.readline().strip()
|
|
33
|
+
browser_title = f.readline().strip()
|
|
34
|
+
matlab_version, session_name = _extract_version_and_session(browser_title)
|
|
35
|
+
timestamp = _get_timestamp(server)
|
|
36
|
+
return timestamp, matlab_version, session_name, address
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _print_server_info_as_table(servers):
|
|
40
|
+
console = Console()
|
|
41
|
+
table = Table(
|
|
42
|
+
title="MATLAB Proxy Servers",
|
|
43
|
+
title_style="cyan",
|
|
44
|
+
title_justify="center",
|
|
45
|
+
caption="No servers found." if not servers else "",
|
|
46
|
+
caption_style="bold red",
|
|
47
|
+
show_header=True,
|
|
48
|
+
header_style="yellow",
|
|
49
|
+
show_lines=True,
|
|
50
|
+
show_edge=True,
|
|
51
|
+
)
|
|
52
|
+
table.add_column("Created On")
|
|
53
|
+
table.add_column("MATLAB\nVersion")
|
|
54
|
+
table.add_column("Session Name")
|
|
55
|
+
table.add_column("Server URL", overflow="fold")
|
|
56
|
+
|
|
57
|
+
# Build server information
|
|
58
|
+
for server in servers:
|
|
59
|
+
table.add_row(*_get_server_info(server))
|
|
60
|
+
|
|
61
|
+
console.print(table)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _get_timestamp(filename):
|
|
65
|
+
"""Get the last modified timestamp of the file in a human-readable format."""
|
|
66
|
+
timestamp = os.path.getmtime(filename)
|
|
67
|
+
readable_time = datetime.fromtimestamp(timestamp).strftime("%d/%m/%y %H:%M:%S")
|
|
68
|
+
return readable_time
|
|
69
|
+
|
|
10
70
|
|
|
11
71
|
def print_server_info():
|
|
12
72
|
"""Print information about all matlab-proxy servers (with version > 0.4.0) running on this machine"""
|
|
@@ -15,30 +75,15 @@ def print_server_info():
|
|
|
15
75
|
# Look for files in port folders
|
|
16
76
|
ports_folder = home_folder / "ports"
|
|
17
77
|
search_string = str(ports_folder) + "/**/mwi_server.info"
|
|
78
|
+
servers = sorted(glob.glob(search_string), key=os.path.getmtime)
|
|
18
79
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
)
|
|
24
|
-
)
|
|
25
|
-
print_output += "\n"
|
|
26
|
-
search_results = sorted(glob.glob(search_string), key=os.path.getmtime)
|
|
27
|
-
if len(search_results) == 0:
|
|
28
|
-
print_output += "No MATLAB-PROXY Servers are currently running."
|
|
29
|
-
else:
|
|
30
|
-
server_number = 0
|
|
31
|
-
for server in search_results:
|
|
32
|
-
server_number += 1
|
|
80
|
+
args = mwi_util.parse_list_cli_args()
|
|
81
|
+
|
|
82
|
+
if args["quiet"]:
|
|
83
|
+
for server in servers:
|
|
33
84
|
with open(server) as f:
|
|
34
85
|
server_info = f.readline().strip()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
boundary_filler="-",
|
|
40
|
-
text_arr=["Thank you."],
|
|
41
|
-
)
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
return print_output
|
|
86
|
+
print(f"{server_info}", end="\n")
|
|
87
|
+
else:
|
|
88
|
+
_print_server_info_as_table(servers)
|
|
89
|
+
return
|
|
@@ -213,3 +213,13 @@ class Experimental:
|
|
|
213
213
|
def should_use_cookie_cache():
|
|
214
214
|
"""Returns true if the cookie jar support is enabled."""
|
|
215
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())
|
matlab_proxy/util/mwi/logger.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Copyright 2020-2025 The MathWorks, Inc.
|
|
2
2
|
"""Functions to access & control the logging behavior of the app"""
|
|
3
3
|
|
|
4
|
+
from . import environment_variables as mwi_env
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.table import Table
|
|
4
9
|
import logging
|
|
5
10
|
import os
|
|
6
11
|
import sys
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from . import environment_variables as mwi_env
|
|
12
|
+
import time
|
|
10
13
|
|
|
11
14
|
logging.getLogger("aiohttp_session").setLevel(logging.ERROR)
|
|
12
15
|
|
|
@@ -47,26 +50,43 @@ def __set_logging_configuration():
|
|
|
47
50
|
Returns:
|
|
48
51
|
Logger: Logger object with the set configuration.
|
|
49
52
|
"""
|
|
50
|
-
#
|
|
53
|
+
# Create the Logger for MATLABProxy
|
|
54
|
+
logger = __get_mw_logger()
|
|
55
|
+
|
|
56
|
+
# log_level is either set by environment or is the default value.
|
|
51
57
|
log_level = os.getenv(
|
|
52
58
|
mwi_env.get_env_name_logging_level(), __get_default_log_level()
|
|
53
59
|
).upper()
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if not valid:
|
|
61
|
+
if __is_invalid_log_level(log_level):
|
|
58
62
|
default_log_level = __get_default_log_level()
|
|
59
|
-
logging.
|
|
63
|
+
logging.warning(
|
|
60
64
|
f"Unknown log level '{log_level}' set. Defaulting to log level '{default_log_level}'..."
|
|
61
65
|
)
|
|
62
66
|
log_level = default_log_level
|
|
63
67
|
|
|
64
|
-
log_file = os.getenv(mwi_env.get_env_name_log_file(), None)
|
|
65
|
-
|
|
66
68
|
## Set logging object
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if mwi_env.Experimental.use_rich_logger():
|
|
70
|
+
from rich.logging import RichHandler
|
|
71
|
+
|
|
72
|
+
rich_handler = RichHandler(
|
|
73
|
+
keywords=[__get_mw_logger_name()],
|
|
74
|
+
)
|
|
75
|
+
rich_handler.setFormatter(logging.Formatter("%(name)s %(message)s"))
|
|
76
|
+
logger.addHandler(rich_handler)
|
|
77
|
+
else:
|
|
78
|
+
colored_formatter = _ColoredFormatter(
|
|
79
|
+
"%(color)s[%(levelname)1.1s %(asctime)s %(name)s]%(end_color)s %(message)s"
|
|
80
|
+
)
|
|
81
|
+
stream_handler = logging.StreamHandler()
|
|
82
|
+
stream_handler.setFormatter(colored_formatter)
|
|
83
|
+
logger.addHandler(stream_handler)
|
|
84
|
+
|
|
85
|
+
logger.setLevel(log_level)
|
|
86
|
+
|
|
87
|
+
log_file = os.getenv(mwi_env.get_env_name_log_file(), None)
|
|
88
|
+
if log_file:
|
|
89
|
+
try:
|
|
70
90
|
log_file = Path(log_file)
|
|
71
91
|
# Need to create the file if it doesn't exist or else logging.FileHandler
|
|
72
92
|
# would open it in 'write' mode instead of 'append' mode.
|
|
@@ -74,27 +94,21 @@ def __set_logging_configuration():
|
|
|
74
94
|
logger.info(f"Initializing logger with log file:{log_file}")
|
|
75
95
|
file_handler = logging.FileHandler(filename=log_file, mode="a")
|
|
76
96
|
formatter = logging.Formatter(
|
|
77
|
-
fmt="%(
|
|
97
|
+
fmt="[%(levelname)s %(asctime)s %(name)s] %(message)s"
|
|
78
98
|
)
|
|
79
99
|
file_handler.setFormatter(formatter)
|
|
80
100
|
file_handler.setLevel(log_level)
|
|
81
101
|
logger.addHandler(file_handler)
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
print(f"Failed to use log file: {log_file} with error: {err}")
|
|
89
|
-
sys.exit(1)
|
|
90
|
-
|
|
91
|
-
# log_level is either set by environment or is the default value.
|
|
92
|
-
logger.info(f"Initializing logger with log_level: {log_level}")
|
|
93
|
-
logger.setLevel(log_level)
|
|
103
|
+
except PermissionError:
|
|
104
|
+
print(
|
|
105
|
+
f"PermissionError: Permission denied to create log file at: {log_file}"
|
|
106
|
+
)
|
|
107
|
+
sys.exit(1)
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
except Exception as err:
|
|
110
|
+
print(f"Failed to use log file: {log_file} with error: {err}")
|
|
111
|
+
sys.exit(1)
|
|
98
112
|
|
|
99
113
|
return logger
|
|
100
114
|
|
|
@@ -120,11 +134,82 @@ def __get_default_log_level():
|
|
|
120
134
|
return "INFO"
|
|
121
135
|
|
|
122
136
|
|
|
123
|
-
def
|
|
137
|
+
def __is_invalid_log_level(log_level):
|
|
124
138
|
"""Helper to check if the log level is valid.
|
|
125
139
|
|
|
126
140
|
Returns:
|
|
127
141
|
Boolean: Whether log level exists
|
|
128
142
|
"""
|
|
129
143
|
|
|
130
|
-
return hasattr(logging, log_level)
|
|
144
|
+
return not hasattr(logging, log_level)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def log_startup_info(title=None, matlab_url=None):
|
|
148
|
+
"""Logs the startup information to the console and log file if specified."""
|
|
149
|
+
logger = __get_mw_logger()
|
|
150
|
+
print_as_table = False
|
|
151
|
+
header_info = "Access MATLAB at:"
|
|
152
|
+
|
|
153
|
+
if sys.stdout.isatty():
|
|
154
|
+
# Width cannot be determined in non-interactive sessions
|
|
155
|
+
console = Console()
|
|
156
|
+
# Number of additional characters used by the table
|
|
157
|
+
padding = 4
|
|
158
|
+
print_as_table = len(matlab_url) + padding <= console.width
|
|
159
|
+
|
|
160
|
+
if print_as_table:
|
|
161
|
+
table = Table(
|
|
162
|
+
caption=title,
|
|
163
|
+
show_header=False,
|
|
164
|
+
show_lines=True,
|
|
165
|
+
show_edge=True,
|
|
166
|
+
highlight=True,
|
|
167
|
+
expand=True,
|
|
168
|
+
)
|
|
169
|
+
table.add_column(overflow="fold", style="bold green", justify="center")
|
|
170
|
+
table.add_row(header_info)
|
|
171
|
+
table.add_row(matlab_url)
|
|
172
|
+
console.print(table)
|
|
173
|
+
|
|
174
|
+
if os.getenv(mwi_env.get_env_name_log_file(), None) or not print_as_table:
|
|
175
|
+
logger.critical(f"{header_info} {matlab_url}")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class _ColoredFormatter(logging.Formatter):
|
|
179
|
+
"""Custom formatter to add colors based on log level and modify time format."""
|
|
180
|
+
|
|
181
|
+
def format(self, record):
|
|
182
|
+
# Example: Add 'color' and 'end_color' attributes based on log level
|
|
183
|
+
if record.levelno == logging.INFO:
|
|
184
|
+
record.color = "\033[32m" # Green
|
|
185
|
+
record.end_color = "\033[0m"
|
|
186
|
+
elif record.levelno == logging.DEBUG:
|
|
187
|
+
record.color = "\033[94m" # Blue
|
|
188
|
+
record.end_color = "\033[0m"
|
|
189
|
+
elif record.levelno == logging.WARNING:
|
|
190
|
+
record.color = "\033[93m" # Yellow
|
|
191
|
+
record.end_color = "\033[0m"
|
|
192
|
+
elif record.levelno == logging.ERROR:
|
|
193
|
+
record.color = "\033[91m" # Red
|
|
194
|
+
record.end_color = "\033[0m"
|
|
195
|
+
elif record.levelno == logging.CRITICAL:
|
|
196
|
+
record.color = "\033[35m" # Magenta
|
|
197
|
+
record.end_color = "\033[0m"
|
|
198
|
+
else:
|
|
199
|
+
record.color = ""
|
|
200
|
+
record.end_color = ""
|
|
201
|
+
|
|
202
|
+
# Call the original format method
|
|
203
|
+
return super().format(record)
|
|
204
|
+
|
|
205
|
+
def formatTime(self, record, datefmt=None):
|
|
206
|
+
# Default behavior of formatTime
|
|
207
|
+
ct = self.converter(record.created)
|
|
208
|
+
if datefmt:
|
|
209
|
+
s = time.strftime(datefmt, ct)
|
|
210
|
+
else:
|
|
211
|
+
t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
|
|
212
|
+
s = "%s,%03d" % (t, record.msecs)
|
|
213
|
+
|
|
214
|
+
# Replace the comma with a period
|
|
215
|
+
return s.replace(",", ".")
|
|
@@ -70,7 +70,7 @@ def validate_mlm_license_file(nlm_connections_str):
|
|
|
70
70
|
# regex = Start of Line, Any number of 0-9 digits , @, any number of nonwhite space characters with "- _ ." allowed
|
|
71
71
|
# "^[0-9]+[@](\w|\_|\-|\.)+$"
|
|
72
72
|
# Server triad is of the form : port@host1 or port@host1,port@host2,port@host3
|
|
73
|
-
nlm_connection_str_regex = "(^[0-9]+[@](\w|\_|\-|\.)+$)"
|
|
73
|
+
nlm_connection_str_regex = r"(^[0-9]+[@](\w|\_|\-|\.)+$)"
|
|
74
74
|
error_message = (
|
|
75
75
|
f"MLM_LICENSE_FILE validation failed for {nlm_connections_str}. "
|
|
76
76
|
f"If set, the MLM_LICENSE_FILE environment variable must contain server names (each of the form port@hostname) separated by ':' on unix or ';' on windows(server triads however must be comma seperated)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: matlab-proxy
|
|
3
|
-
Version: 0.27.
|
|
3
|
+
Version: 0.27.3
|
|
4
4
|
Summary: Python® package enables you to launch MATLAB® and access it from a web browser.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mathworks/matlab-proxy/
|
|
6
6
|
Project-URL: Documentation, https://github.com/mathworks/matlab-proxy/blob/main/README.md
|
|
@@ -23,6 +23,7 @@ Requires-Dist: importlib-metadata
|
|
|
23
23
|
Requires-Dist: importlib-resources
|
|
24
24
|
Requires-Dist: psutil
|
|
25
25
|
Requires-Dist: requests
|
|
26
|
+
Requires-Dist: rich
|
|
26
27
|
Requires-Dist: watchdog
|
|
27
28
|
Provides-Extra: dev
|
|
28
29
|
Requires-Dist: aiohttp-devtools; extra == 'dev'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
|
|
2
|
-
matlab_proxy/app.py,sha256=
|
|
3
|
-
matlab_proxy/app_state.py,sha256=
|
|
2
|
+
matlab_proxy/app.py,sha256=GKZ7X99Wp3GYG6uBymgURz0iskSi5TvoXn3LX4AkXm0,38036
|
|
3
|
+
matlab_proxy/app_state.py,sha256=XTonzW869Uaco1du3wI4suI_QqZkP-Vycj4zifOF3aE,73498
|
|
4
4
|
matlab_proxy/constants.py,sha256=gYpS3mls1i3cO4eExbqQO-z_h8QIWTkM9h2S_EAMWSU,1257
|
|
5
5
|
matlab_proxy/default_configuration.py,sha256=7xjsCzma4c6u0rEzio8xhHaDRy0wY2xtGXuARY2v0hc,1881
|
|
6
6
|
matlab_proxy/devel.py,sha256=nR6XPVBUEdQ-RZGtYvX1YHTp8gj9cuw5Hp8ahasMBc8,14310
|
|
7
|
-
matlab_proxy/settings.py,sha256=
|
|
7
|
+
matlab_proxy/settings.py,sha256=x3N7DJXh4DMPlllYFGI9iAIzVsHPLvrFWawJLmO04t8,29400
|
|
8
8
|
matlab_proxy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
matlab_proxy/gui/favicon.ico,sha256=7w7Ki1uQP2Rgwc64dOV4-NrTu97I3WsZw8OvRSoY1A0,130876
|
|
10
10
|
matlab_proxy/gui/index.html,sha256=pe177w98jAUrizWJ7DPQB87_rWobCK5QDHD1YfERSs8,720
|
|
@@ -39,22 +39,22 @@ matlab_proxy/gui/static/media/trigger-ok.Dzg8OIrk.svg,sha256=mD-7N9cc4ARdMBFcpln
|
|
|
39
39
|
matlab_proxy/icons/matlab.svg,sha256=xh5uYebQd8I-ISvenjU9A-PkClzW_lU9wvm3doXOFKM,13366
|
|
40
40
|
matlab_proxy/matlab/evaluateUserMatlabCode.m,sha256=R8w6nPdGtadR4UUFJaspcrGQL7cJwUItdrfc531w3bM,2420
|
|
41
41
|
matlab_proxy/matlab/startup.m,sha256=UcA4i2lAMytwBsO783uPIQoP5Pzw1R0xrUywbBBtTjw,533
|
|
42
|
-
matlab_proxy/util/__init__.py,sha256=
|
|
42
|
+
matlab_proxy/util/__init__.py,sha256=pelRJiSNKkEcE6dxj609QJCJ-NByq_FBHMUXGnJZRy0,11155
|
|
43
43
|
matlab_proxy/util/cookie_jar.py,sha256=GceKyB53lTX5r2wp9myvf0JDWDfvSamvjb4zmjkoOtY,2401
|
|
44
44
|
matlab_proxy/util/event_loop.py,sha256=sX_0tKlirCY5ImLxkss_XO4Ksj65u6JHtwMj25oGL94,1816
|
|
45
|
-
matlab_proxy/util/list_servers.py,sha256=
|
|
45
|
+
matlab_proxy/util/list_servers.py,sha256=so6nj32xGNGLrua4qu5FA5jiDsocVDP-RehthtLwctk,3004
|
|
46
46
|
matlab_proxy/util/mw.py,sha256=dLGSdfcTZiwKR1MMZA-39o-8na13IEPZOGBqcaHmKVI,11086
|
|
47
47
|
matlab_proxy/util/system.py,sha256=XoT3Rv5MwPkdfhk2oMvUwxxlzZmADMlxzi9IRQyGgbA,1692
|
|
48
48
|
matlab_proxy/util/windows.py,sha256=_5gl2IyHIfw8-D3_G5uHkycZVGGFVXtjkd6_aP3g2Ts,3785
|
|
49
49
|
matlab_proxy/util/mwi/__init__.py,sha256=zI-X1lafr8H3j17PyA0oSZ0q5nINfK-WDA7VmJKmSAQ,158
|
|
50
50
|
matlab_proxy/util/mwi/custom_http_headers.py,sha256=kfDjSnEXEVzoF2pZuEn76LKayeD2WKoQEDu2Y9EMOAo,7154
|
|
51
51
|
matlab_proxy/util/mwi/download.py,sha256=-GJj3yOsL4vF_9baqRXkgBI-vu_OwjZMQVkJXFS8GMc,4965
|
|
52
|
-
matlab_proxy/util/mwi/environment_variables.py,sha256=
|
|
52
|
+
matlab_proxy/util/mwi/environment_variables.py,sha256=2diNgBbDDaM67aVHycYNczjViY3zc-w7QN2TVTJv43o,7485
|
|
53
53
|
matlab_proxy/util/mwi/exceptions.py,sha256=8o4PZmira_ZonnOROzu8ERIiSn9y-456JO89gqjCags,5446
|
|
54
|
-
matlab_proxy/util/mwi/logger.py,sha256=
|
|
54
|
+
matlab_proxy/util/mwi/logger.py,sha256=1ndW0VPqPNjuGT8wK8x771qD5JBtUoQe-kZFluzS_RA,6785
|
|
55
55
|
matlab_proxy/util/mwi/session_name.py,sha256=HQAGMlJo6KMb2f9MBcavni48nw9H-cHWMeJKmXxpeys,915
|
|
56
56
|
matlab_proxy/util/mwi/token_auth.py,sha256=CEmWcz8LCBnt4Z73CTLhz2-awZaJgw8oi4eqaHN0MRU,10000
|
|
57
|
-
matlab_proxy/util/mwi/validators.py,sha256=
|
|
57
|
+
matlab_proxy/util/mwi/validators.py,sha256=wLVU0M7on1PvHDhwH25qx_TxeYSHh5RoF3sJQvHMrBI,13239
|
|
58
58
|
matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=Vfl2hNC7V1IwoK9_wrwfENs4BC8P-Mvvqh4BNGi2n48,119
|
|
59
59
|
matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=kpIgJN0AqYLeX56UylWgB0t07fg8sh0RhIlUH_8JitM,3654
|
|
60
60
|
matlab_proxy/util/mwi/embedded_connector/request.py,sha256=RXoVvrm5fibVb2A6EZnkMWwAQkYX3J5kqDTGQDZo9p0,4316
|
|
@@ -80,8 +80,8 @@ matlab_proxy_manager/web/__init__.py,sha256=KfwQxxM5a1kMRtNbhz8tb7YfHp8e2d0tNLB5
|
|
|
80
80
|
matlab_proxy_manager/web/app.py,sha256=-sfeJ4ltvcT1-8m0rOZkn357XQTSSNSPIUb3fidT71Y,20643
|
|
81
81
|
matlab_proxy_manager/web/monitor.py,sha256=PWkwV0kP3XHCxDRHpurPh74Zg-SgaIXnCnX2xZSW_R8,1541
|
|
82
82
|
matlab_proxy_manager/web/watcher.py,sha256=89JHjBAQtOrllstaJFxqrjHwckpRmu3qfUqeqPLmH2Q,2130
|
|
83
|
-
matlab_proxy-0.27.
|
|
84
|
-
matlab_proxy-0.27.
|
|
85
|
-
matlab_proxy-0.27.
|
|
86
|
-
matlab_proxy-0.27.
|
|
87
|
-
matlab_proxy-0.27.
|
|
83
|
+
matlab_proxy-0.27.3.dist-info/METADATA,sha256=txtH2wTi8d3bjLrALZVMJwJtcPuzWICJB3sg6j8L8Kw,11343
|
|
84
|
+
matlab_proxy-0.27.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
85
|
+
matlab_proxy-0.27.3.dist-info/entry_points.txt,sha256=3wztwXpt6wdGfTwscc4qHbCeWzi0E2XhyJbMDndyQKc,304
|
|
86
|
+
matlab_proxy-0.27.3.dist-info/licenses/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
|
|
87
|
+
matlab_proxy-0.27.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|