matlab-proxy 0.14.0__py3-none-any.whl → 0.15.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matlab-proxy might be problematic. Click here for more details.

Files changed (50) hide show
  1. matlab_proxy/app.py +52 -10
  2. matlab_proxy/constants.py +1 -0
  3. matlab_proxy/gui/asset-manifest.json +3 -3
  4. matlab_proxy/gui/index.html +1 -1
  5. matlab_proxy/gui/static/js/{main.14aa7840.js → main.ff1bfd69.js} +3 -3
  6. matlab_proxy/gui/static/js/main.ff1bfd69.js.map +1 -0
  7. matlab_proxy/util/__init__.py +8 -1
  8. matlab_proxy/util/mwi/download.py +145 -0
  9. matlab_proxy/util/mwi/embedded_connector/helpers.py +1 -1
  10. matlab_proxy/util/mwi/embedded_connector/request.py +1 -1
  11. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/METADATA +1 -1
  12. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/RECORD +49 -16
  13. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/top_level.txt +1 -0
  14. tests/integration/__init__.py +1 -0
  15. tests/integration/integration_tests_with_license/__init__.py +1 -0
  16. tests/integration/integration_tests_with_license/conftest.py +47 -0
  17. tests/integration/integration_tests_with_license/test_http_end_points.py +223 -0
  18. tests/integration/integration_tests_without_license/__init__.py +1 -0
  19. tests/integration/integration_tests_without_license/conftest.py +115 -0
  20. tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py +49 -0
  21. tests/integration/utils/__init__.py +1 -0
  22. tests/integration/utils/integration_tests_utils.py +352 -0
  23. tests/integration/utils/licensing.py +152 -0
  24. tests/unit/__init__.py +1 -0
  25. tests/unit/conftest.py +67 -0
  26. tests/unit/test_app.py +1113 -0
  27. tests/unit/test_app_state.py +582 -0
  28. tests/unit/test_constants.py +5 -0
  29. tests/unit/test_ddux.py +22 -0
  30. tests/unit/test_devel.py +246 -0
  31. tests/unit/test_non_dev_mode.py +169 -0
  32. tests/unit/test_settings.py +460 -0
  33. tests/unit/util/__init__.py +3 -0
  34. tests/unit/util/mwi/__init__.py +1 -0
  35. tests/unit/util/mwi/embedded_connector/__init__.py +1 -0
  36. tests/unit/util/mwi/embedded_connector/test_helpers.py +29 -0
  37. tests/unit/util/mwi/embedded_connector/test_request.py +64 -0
  38. tests/unit/util/mwi/test_custom_http_headers.py +281 -0
  39. tests/unit/util/mwi/test_logger.py +49 -0
  40. tests/unit/util/mwi/test_token_auth.py +289 -0
  41. tests/unit/util/mwi/test_validators.py +331 -0
  42. tests/unit/util/test_mw.py +550 -0
  43. tests/unit/util/test_util.py +135 -0
  44. tests/utils/__init__.py +1 -0
  45. tests/utils/logging_util.py +81 -0
  46. matlab_proxy/gui/static/js/main.14aa7840.js.map +0 -1
  47. /matlab_proxy/gui/static/js/{main.14aa7840.js.LICENSE.txt → main.ff1bfd69.js.LICENSE.txt} +0 -0
  48. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/LICENSE.md +0 -0
  49. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/WHEEL +0 -0
  50. {matlab_proxy-0.14.0.dist-info → matlab_proxy-0.15.1.dist-info}/entry_points.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  import argparse
4
4
  import os
5
5
  import socket
6
+ import time
6
7
 
7
8
  from pathlib import Path
8
9
 
@@ -198,7 +199,9 @@ def get_child_processes(parent_process):
198
199
  # to get hold child processes
199
200
  parent_process_psutil = psutil.Process(parent_process.pid)
200
201
 
201
- while True:
202
+ max_attempts = 10
203
+ child_processes = None
204
+ for _ in range(max_attempts):
202
205
  try:
203
206
  # Before checking for any child processes, ensure that the parent process is running
204
207
  assert (
@@ -216,6 +219,10 @@ def get_child_processes(parent_process):
216
219
 
217
220
  if child_processes:
218
221
  break
222
+ time.sleep(0.1)
223
+
224
+ if not child_processes:
225
+ raise RuntimeError("No child processes found after multiple attempts.")
219
226
 
220
227
  return child_processes
221
228
 
@@ -0,0 +1,145 @@
1
+ # Copyright 2024 The MathWorks, Inc.
2
+
3
+ # This file contains functions required to enable downloads from the file browser
4
+ from matlab_proxy.util.mwi import logger as mwi_logger
5
+ from matlab_proxy.util import mwi, system
6
+
7
+ logger = mwi_logger.get()
8
+
9
+
10
+ def _is_null_base_url(base_url):
11
+ return base_url == "/" or base_url == ""
12
+
13
+
14
+ def is_download_request(req):
15
+ """
16
+ Determine if the incoming request is for a download action.
17
+
18
+ This function checks if the request's relative URL path starts with
19
+ '/download/' or with '{base_url}/download/', depending on the base URL
20
+ specified in the application settings.
21
+
22
+ Parameters:
23
+ req (HTTPRequest): HTTPRequest Object
24
+
25
+ Returns:
26
+ - bool: True if the request is for a download, False otherwise.
27
+ ```
28
+ """
29
+
30
+ base_url = req.app["settings"]["base_url"]
31
+ if _is_null_base_url(base_url):
32
+ return req.rel_url.path.startswith("/download")
33
+ else:
34
+ return req.rel_url.path.startswith(f"{base_url}/download")
35
+
36
+
37
+ async def get_download_url(req):
38
+ """
39
+ Asynchronously generates a download URL for a file.
40
+
41
+ This function takes a request object, extracts the full path to the file, and
42
+ uses the MATLAB Web Interface (MWI) to generate a download URL for that file.
43
+ It logs the full path and the response from the MWI. If successful, it returns
44
+ the download URL; otherwise, it returns None.
45
+
46
+ Parameters:
47
+ The request object containing necessary information to process the download.
48
+ Returns:
49
+ The download URL string if successful, None otherwise.
50
+ Raises:
51
+ Logs an error message and returns None if an error occurs.
52
+ """
53
+ full_path_to_file = _get_download_payload_path(req)
54
+ logger.debug(f"full_path_to_file: {full_path_to_file}")
55
+
56
+ args = [full_path_to_file, 1.0]
57
+ data = mwi.embedded_connector.helpers.get_data_to_feval_mcode(
58
+ "matlab.ui.internal.URLUtils.getURLToUserFile", *args, nargout=1
59
+ )
60
+
61
+ try:
62
+ state = req.app["state"]
63
+ headers = state._get_token_auth_headers()
64
+ url = mwi.embedded_connector.helpers.get_mvm_endpoint(
65
+ state.settings["mwi_server_url"]
66
+ )
67
+ resp_json = await mwi.embedded_connector.send_request(
68
+ url=url,
69
+ method="POST",
70
+ data=data,
71
+ headers=headers,
72
+ )
73
+
74
+ logger.debug(f"EC Response URL: {resp_json}")
75
+
76
+ resp = resp_json["messages"]["FEvalResponse"][0]
77
+
78
+ if not resp["isError"]:
79
+ # No error detected, proceed to fetch the results
80
+ download_url = resp["results"][0]
81
+ logger.debug(f"download_url: {download_url}")
82
+ base_url = req.app["settings"]["base_url"]
83
+ return (
84
+ download_url
85
+ if _is_null_base_url(base_url)
86
+ else f"{base_url}{download_url}"
87
+ )
88
+
89
+ except KeyError as key_err:
90
+ logger.error(f"Invalid Key Usage Detected! Check key: {key_err}")
91
+ pass
92
+
93
+ except Exception as err:
94
+ logger.error(
95
+ f"Failed to create download url from the Embedded Connector due to err: {err}"
96
+ )
97
+ pass
98
+
99
+ # In case of any failures.
100
+ return None
101
+
102
+
103
+ def _get_download_payload_path(req):
104
+ """
105
+ Constructs the file system path to the payload for a download request.
106
+
107
+ This function analyzes the incoming request to determine the intended file path
108
+ for download. It takes into account the base URL from the application settings,
109
+ the nature of the request (whether it's a download request), and the operating
110
+ system to format the path correctly. The function supports different path
111
+ formatting for Windows and Unix-like systems due to their differences in file
112
+ system path syntax.
113
+
114
+ Note:
115
+ This function is intended to be used internally and starts with an underscore
116
+ to indicate it is a private member of the module.
117
+
118
+ Args:
119
+ req: An object representing the incoming request, which includes the relative
120
+ URL from which the file path can be deduced.
121
+
122
+ Returns:
123
+ A string representing the file system path to the requested download payload,
124
+ or None if the request is not a download request.
125
+ """
126
+ base_url = req.app["settings"]["base_url"]
127
+ if is_download_request(req):
128
+ from pathlib import Path
129
+
130
+ compare_str = (
131
+ "/download" if _is_null_base_url(base_url) else f"{base_url}/download"
132
+ )
133
+
134
+ if system.is_windows():
135
+ # On Windows, the URL is of the form : /downloadC:\some\path\to\file.txt
136
+ return str(
137
+ Path((req.rel_url.path).replace("/download", "/download/")).relative_to(
138
+ f"{compare_str}"
139
+ )
140
+ )
141
+ else:
142
+ # On Posix, the URL is of the form : /download/some/path/to/file.txt
143
+ return "/" + str(Path((req.rel_url.path)).relative_to(f"{compare_str}"))
144
+
145
+ return None
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020-2022 The MathWorks, Inc.
1
+ # Copyright 2020-2024 The MathWorks, Inc.
2
2
 
3
3
  """ This file contains helper methods which return the details required for sending
4
4
  a HTTP request to the Embedded Connector. """
@@ -106,7 +106,7 @@ async def get_state(mwi_server_url, headers=None):
106
106
  return "up"
107
107
  except Exception as err:
108
108
  logger.debug(
109
- f"{err}: Embbeded connector is currently not responding to ping requests."
109
+ f"{err}: Embedded connector is currently not responding to ping requests."
110
110
  )
111
111
  pass
112
112
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: matlab-proxy
3
- Version: 0.14.0
3
+ Version: 0.15.1
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,14 +1,14 @@
1
1
  matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
2
- matlab_proxy/app.py,sha256=Fd8kbdLF72LHZq_QptKeQc1Qti4TTF1kOJh_Sa1hd3U,32260
2
+ matlab_proxy/app.py,sha256=-QcfNOCyXAQu58Gq-bSU4iHtJrVglxgD0c-n6nTzumo,33819
3
3
  matlab_proxy/app_state.py,sha256=HV4_igTkUVf-CQWPKc7s3z4Ea_MkSBbV7k3I-AG-m28,55374
4
- matlab_proxy/constants.py,sha256=GTuIP6ibk1HcoxVihBRcy7SOfoQdb4hy0vhj2nH99sc,910
4
+ matlab_proxy/constants.py,sha256=k9vESSF1HSrr2-tCgIEomJ47Q7UR4wbrMCWzZnLLoPc,924
5
5
  matlab_proxy/default_configuration.py,sha256=DxQaHzAivzstiPl_nDfxs8SOyP9oaK9v3RP4LtroJl4,843
6
6
  matlab_proxy/devel.py,sha256=nR6XPVBUEdQ-RZGtYvX1YHTp8gj9cuw5Hp8ahasMBc8,14310
7
7
  matlab_proxy/settings.py,sha256=YjchyZAzvLfl-CiwxAPtSaTTo7aRgD6inS4-jZmsuNY,24687
8
8
  matlab_proxy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- matlab_proxy/gui/asset-manifest.json,sha256=0eynKD0QHNdOgsiH3IuXXNkRQph4sd_QV4S89qocW2k,3516
9
+ matlab_proxy/gui/asset-manifest.json,sha256=2i4oSd9fAzwDgW_jBPUrOvvrelhiEh0iUIXge7tpVZ4,3516
10
10
  matlab_proxy/gui/favicon.ico,sha256=7w7Ki1uQP2Rgwc64dOV4-NrTu97I3WsZw8OvRSoY1A0,130876
11
- matlab_proxy/gui/index.html,sha256=IxsvWXcW8bVcVPdnnMQoolow1BFirTUyCo-O9uYGYTQ,637
11
+ matlab_proxy/gui/index.html,sha256=iSRij24ekBNqZqWd0urs_FUmEs9lrbf9mIBMpLXNlB0,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
@@ -16,9 +16,9 @@ matlab_proxy/gui/static/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
16
16
  matlab_proxy/gui/static/css/main.47712126.css,sha256=OT5ccyC0a6fVg956C-8b6uDVbZZVgcpXbHjdO6v4ZBI,274313
17
17
  matlab_proxy/gui/static/css/main.47712126.css.map,sha256=RdfmXfQvzvvh4XZuDWShm8CD8pA2Gb2K6MtMzrgJyKM,350495
18
18
  matlab_proxy/gui/static/js/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- matlab_proxy/gui/static/js/main.14aa7840.js,sha256=Eu6ZKinNe4gYoD1KV-CsYDJHg0DNKVq4-Qxy2sT2A-U,294128
20
- matlab_proxy/gui/static/js/main.14aa7840.js.LICENSE.txt,sha256=3cj3DrwM51esz1ogL9VVU1ZyXyXJ6u-Ec2CI9CCcI_A,1689
21
- matlab_proxy/gui/static/js/main.14aa7840.js.map,sha256=JbKOBbRaQIVoticAYynd6nEc1msGas1RXxnzvA1eWDs,935545
19
+ matlab_proxy/gui/static/js/main.ff1bfd69.js,sha256=hu8hJKKivhC7JHB7mRjzRf1bz503WR5fX7FiIPhdPJ4,294194
20
+ matlab_proxy/gui/static/js/main.ff1bfd69.js.LICENSE.txt,sha256=3cj3DrwM51esz1ogL9VVU1ZyXyXJ6u-Ec2CI9CCcI_A,1689
21
+ matlab_proxy/gui/static/js/main.ff1bfd69.js.map,sha256=y7nJxSw1bPSVkRLkIoFB6WxvoTGwbUR26MlqSz8mQ5U,937068
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,7 +53,7 @@ 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/startup.m,sha256=YRtI8P2flDJSDcPxJ2008B2l1T9JpqiUbzhQxA0frbc,1558
56
- matlab_proxy/util/__init__.py,sha256=bRfvYEbxsaiYhtWq5imTZM7PRrSEJ7GTlVBptvunaYQ,7902
56
+ matlab_proxy/util/__init__.py,sha256=ikj07VxQdIThUWzWLOrdIsO-R1VtEhunB0mjrfnD5jE,8114
57
57
  matlab_proxy/util/event_loop.py,sha256=Zqd282jlvPHHyc4kg8IjIzlzh9zLM_SAc5xjqUOrm04,1144
58
58
  matlab_proxy/util/list_servers.py,sha256=M93coVZjyQCdIvCCxsNOU_XDWNjBSysOJ5tWXaTjP8Y,1369
59
59
  matlab_proxy/util/mw.py,sha256=dLGSdfcTZiwKR1MMZA-39o-8na13IEPZOGBqcaHmKVI,11086
@@ -61,17 +61,50 @@ matlab_proxy/util/system.py,sha256=XoT3Rv5MwPkdfhk2oMvUwxxlzZmADMlxzi9IRQyGgbA,1
61
61
  matlab_proxy/util/windows.py,sha256=R9-VA7f0snVanSR7IgbHz3kvSnthZuUYe2UhBd5QWMQ,3440
62
62
  matlab_proxy/util/mwi/__init__.py,sha256=zI-X1lafr8H3j17PyA0oSZ0q5nINfK-WDA7VmJKmSAQ,158
63
63
  matlab_proxy/util/mwi/custom_http_headers.py,sha256=kfDjSnEXEVzoF2pZuEn76LKayeD2WKoQEDu2Y9EMOAo,7154
64
+ matlab_proxy/util/mwi/download.py,sha256=-GJj3yOsL4vF_9baqRXkgBI-vu_OwjZMQVkJXFS8GMc,4965
64
65
  matlab_proxy/util/mwi/environment_variables.py,sha256=bIz0QFWo0pgyvSeJ_kAobUCS17V05CSmFWm3zYIOIsA,7139
65
66
  matlab_proxy/util/mwi/exceptions.py,sha256=93HrHbOq24KI4Md2el23XN01wIqVShEK29Pbt2V0Jr8,4628
66
67
  matlab_proxy/util/mwi/logger.py,sha256=e7wTPclrtJ-aX5mPk_pUJMX7-1QD_snGBW1P2ks-ETE,3311
67
68
  matlab_proxy/util/mwi/token_auth.py,sha256=25uQE2cul6MZNTj1HQqukiBS014dj7URZfMOFPKcS3Y,9606
68
69
  matlab_proxy/util/mwi/validators.py,sha256=BMMOD-0tdjGIALm1MmG4yXVRoD2ZUXkrJXLWP_D5FGo,11712
69
70
  matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=SVSckEJ4zQQ2KkNPT_un8ndMAImcMOTrai7ShAbmFY4,114
70
- matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=SfrwpCnZ6QGJBko-sR2bIG4-_qZOn29zCZV9qwVBnkM,3395
71
- matlab_proxy/util/mwi/embedded_connector/request.py,sha256=EaQfV2R5lhzfnob0rZG2Eb9rl7BYd7_ZyK0jNIZzH6g,3730
72
- matlab_proxy-0.14.0.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
73
- matlab_proxy-0.14.0.dist-info/METADATA,sha256=R6iheeeUFTuovrhUK0SuSe1coTJK1-kJE925p7TrKhA,10108
74
- matlab_proxy-0.14.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
75
- matlab_proxy-0.14.0.dist-info/entry_points.txt,sha256=DbBLYgnRt8UGiOpd0zHigRTyyMdZYhMdvCvSYP7wPN0,244
76
- matlab_proxy-0.14.0.dist-info/top_level.txt,sha256=3-Lxje1LZvSfK__TVoRksU4th_PCj6cMMJwhH8P0_3I,13
77
- matlab_proxy-0.14.0.dist-info/RECORD,,
71
+ matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=p6TedefbvhlZT64IMwFjrb0panWCXf-T3XPoztDbxM0,3391
72
+ matlab_proxy/util/mwi/embedded_connector/request.py,sha256=-6DL9K8JWjX5u5XVOEGaqBUIwQ-oCVW30-VP3qk_rzw,3730
73
+ tests/integration/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
74
+ tests/integration/integration_tests_with_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
75
+ tests/integration/integration_tests_with_license/conftest.py,sha256=sCaIXB8d4vf05C7JWSVA7g5gnPjbpRq3dftuBpWyp1s,1599
76
+ tests/integration/integration_tests_with_license/test_http_end_points.py,sha256=fDA2VyauxM8x0Gw9ArZLI4YFOVduX6Wg-UiHdr5tmHk,7411
77
+ tests/integration/integration_tests_without_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
78
+ tests/integration/integration_tests_without_license/conftest.py,sha256=z5r_hALWo7Lh0kyN-h1N2oCj1jIug3-0RXQm92XTtPI,3426
79
+ tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py,sha256=tkdyhfZBpfJpbnEzjURyV-GE0p43YxOa9xooJf-JoM4,1653
80
+ tests/integration/utils/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
81
+ tests/integration/utils/integration_tests_utils.py,sha256=IbJ9CedFHiz3k85FBY-8GwotTnjPF3jF4AHdKio7jqk,10321
82
+ tests/integration/utils/licensing.py,sha256=rEBjvMXO8R3mL6KnePu2lojmOsjD4GXl9frf9N0Wacs,4842
83
+ tests/unit/__init__.py,sha256=KfwQxxM5a1kMRtNbhz8tb7YfHp8e2d0tNLB55wYvDS8,37
84
+ tests/unit/conftest.py,sha256=Hfxq3h8IZuLJkRMh5jdEFiq78CIAdKvm-6KryRDZ0FY,1918
85
+ tests/unit/test_app.py,sha256=0JK5xak31wIC_of5fNAtoCgi6E-z4JR-AAqtIlNAZ0k,37313
86
+ tests/unit/test_app_state.py,sha256=M1jsEVfg4XnseQ_PSJjcCm40extosayRaA7NzdJ9FkY,18596
87
+ tests/unit/test_constants.py,sha256=ZSsj1-xHrlqxhnjv2x2een6E_U2vSCONoQVWO_QpbYI,124
88
+ tests/unit/test_ddux.py,sha256=a2J2iM8j_nnfJVuMI38p5AjwrRdoMj3N88gFgS2I4hg,713
89
+ tests/unit/test_devel.py,sha256=A-1iVhSSwmywaW65QIRcUS2Fk7nJxceCcCm7CJtNdEc,7982
90
+ tests/unit/test_non_dev_mode.py,sha256=0v27y27SLOWvw6jf_GhLLNg-RMsZS_OyGAnqoQYPpSA,5515
91
+ tests/unit/test_settings.py,sha256=6KuYcOIqilR5RmaYxHw5mr_4CqDS3iMsouS-IrT9wGk,16644
92
+ tests/unit/util/__init__.py,sha256=GInSQBb2SoVD5LZfmSCQa9-UZJT_UP-jNfrojkgCybU,87
93
+ tests/unit/util/test_mw.py,sha256=YC4mjn6G6_XuHELt8uW9F6g2K0_fWtQl1R0kWFvWbAo,18565
94
+ tests/unit/util/test_util.py,sha256=jhZOgErpD6b3JeusLBOPVvu6iZ3_ttwlEVV8uKLUvrw,5060
95
+ tests/unit/util/mwi/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
96
+ tests/unit/util/mwi/test_custom_http_headers.py,sha256=UfrhclS0j6WhShtg1ki2oF1kK8JqRC29uevH4tuDqF4,11182
97
+ tests/unit/util/mwi/test_logger.py,sha256=zWImNitMYKPJunXWJjEDEtCEKwBz615PC844ZLwoxIg,1845
98
+ tests/unit/util/mwi/test_token_auth.py,sha256=-G5u4tFYefhzb-W4tTS-F4HxNYxNNrPa0FOLncHjMN8,10173
99
+ tests/unit/util/mwi/test_validators.py,sha256=YeOP0-T7SFNeiC7JIQj7cV4ja3d6PhswsTz27IEgJHQ,10852
100
+ tests/unit/util/mwi/embedded_connector/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
101
+ tests/unit/util/mwi/embedded_connector/test_helpers.py,sha256=vYTWNUTuDeaygo16JGMTvWeI_CLOnvPkwNJmLndvJhE,890
102
+ tests/unit/util/mwi/embedded_connector/test_request.py,sha256=PR-jddnXDEiip-lD7A_QSvRwEkwo3eQ8owZlk-r9vnk,1867
103
+ tests/utils/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
104
+ tests/utils/logging_util.py,sha256=VBy_NRvwau3C_CVTBjK5RMROrQimnJYHO2U0aKSZiRw,2234
105
+ matlab_proxy-0.15.1.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
106
+ matlab_proxy-0.15.1.dist-info/METADATA,sha256=P95V-BiQ49UlFBPIFIEwMm_gpjfFmutEHKBW3VMPH-Q,10108
107
+ matlab_proxy-0.15.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
108
+ matlab_proxy-0.15.1.dist-info/entry_points.txt,sha256=DbBLYgnRt8UGiOpd0zHigRTyyMdZYhMdvCvSYP7wPN0,244
109
+ matlab_proxy-0.15.1.dist-info/top_level.txt,sha256=9uVTjsUCAS4TwsxueTBxrBg3PdBiTSsYowAkHPv9VY0,19
110
+ matlab_proxy-0.15.1.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ # Copyright 2023-2024 The MathWorks, Inc.
@@ -0,0 +1 @@
1
+ # Copyright 2023 The MathWorks, Inc.
@@ -0,0 +1,47 @@
1
+ # Copyright 2023-2024 The MathWorks, Inc.
2
+
3
+ import os
4
+ from tests.integration.utils import integration_tests_utils as utils
5
+ import pytest
6
+ from matlab_proxy.util.mwi import environment_variables as mwi_env
7
+ from tests.utils.logging_util import create_integ_test_logger
8
+
9
+
10
+ _logger = create_integ_test_logger(
11
+ __name__, log_file_path=os.getenv("MWI_INTEG_TESTS_LOG_FILE_PATH")
12
+ )
13
+
14
+
15
+ @pytest.fixture(scope="module", name="module_monkeypatch")
16
+ def monkeypatch_module_scope_fixture():
17
+ """
18
+ To ensure that modifications made with the monkeypatch fixture
19
+ persist across all tests in the module, this fixture
20
+ has been created in 'module' scope. This is done because a 'module'
21
+ scope object is needed with matlab-proxy 'module' scope fixture.
22
+ This allows us to patch certain aspects, like environment variables,
23
+ for all tests within the module.
24
+
25
+ Yields:
26
+ class object: Object of class MonkeyPatch
27
+ """
28
+ with pytest.MonkeyPatch.context() as mp:
29
+ yield mp
30
+
31
+
32
+ @pytest.fixture(autouse=True, scope="module")
33
+ def matlab_proxy_fixture(module_monkeypatch, request):
34
+ """
35
+ Pytest fixture for managing a standalone matlab-proxy process
36
+ for testing purposes. This fixture sets up a matlab-proxy process in
37
+ the module scope, and tears it down after all the tests are executed.
38
+ """
39
+
40
+ utils.perform_basic_checks()
41
+
42
+ module_monkeypatch.setenv(mwi_env.get_env_name_testing(), "false")
43
+ module_monkeypatch.setenv(mwi_env.get_env_name_development(), "false")
44
+ _logger.info("Started MATLAB Proxy process")
45
+
46
+ # Run the matlab proxy tests
47
+ yield
@@ -0,0 +1,223 @@
1
+ # Copyright 2023-2024 The MathWorks, Inc.
2
+
3
+ import json
4
+ import os
5
+ import time
6
+ import matlab_proxy.settings as settings
7
+ from tests.integration.utils import integration_tests_utils as utils
8
+ import pytest
9
+ from matlab_proxy.util import system
10
+ import requests
11
+ import re
12
+ from requests.adapters import HTTPAdapter, Retry
13
+ from urllib.parse import urlparse, parse_qs
14
+ from tests.utils.logging_util import create_integ_test_logger
15
+ from logging import DEBUG
16
+
17
+ _logger = create_integ_test_logger(__name__)
18
+
19
+ # Timeout for polling the matlab-proxy http endpoints
20
+ # matlab proxy in Mac machines takes more time to be 'up'
21
+
22
+ MAX_TIMEOUT = settings.get_process_startup_timeout()
23
+
24
+
25
+ class RealMATLABServer:
26
+ """
27
+ Context Manager class which returns matlab proxy web server serving real MATLAB
28
+ for testing.
29
+
30
+ Setting up the server in the context of Pytest.
31
+ """
32
+
33
+ def __init__(self, event_loop):
34
+ self.event_loop = event_loop
35
+
36
+ def __enter__(self):
37
+ # Store the matlab proxy logs in os.pipe for testing
38
+ # os.pipe2 is only supported in Linux systems
39
+ _logger.info("Setting up MATLAB Server for integration test")
40
+
41
+ _logger.debug("Entering RealMATLABServer enter section.")
42
+ self.dpipe = os.pipe2(os.O_NONBLOCK) if system.is_linux() else os.pipe()
43
+ self.mwi_app_port = utils.get_random_free_port()
44
+ self.matlab_config_file_path = str(utils.get_matlab_config_file())
45
+
46
+ self.temp_dir_path = os.path.dirname(
47
+ os.path.dirname(self.matlab_config_file_path)
48
+ )
49
+
50
+ self.temp_dir_name = "temp_dir"
51
+ self.mwi_base_url = "/matlab-test"
52
+
53
+ # Environment variables to launch matlab proxy
54
+ input_env = {
55
+ "MWI_APP_PORT": self.mwi_app_port,
56
+ "MWI_BASE_URL": self.mwi_base_url,
57
+ }
58
+
59
+ self.proc = self.event_loop.run_until_complete(
60
+ utils.start_matlab_proxy_app(out=self.dpipe[1], input_env=input_env)
61
+ )
62
+
63
+ utils.wait_server_info_ready(self.mwi_app_port)
64
+ parsed_url = urlparse(utils.get_connection_string(self.mwi_app_port))
65
+
66
+ self.headers = {
67
+ "mwi_auth_token": (
68
+ parse_qs(parsed_url.query)["mwi_auth_token"][0]
69
+ if "mwi_auth_token" in parse_qs(parsed_url.query)
70
+ else ""
71
+ )
72
+ }
73
+ self.connection_scheme = parsed_url.scheme
74
+ self.url = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path
75
+ return self
76
+
77
+ async def _terminate_process(self, timeout=0):
78
+ """
79
+ Asynchronous helper method to terminate the process with a timeout.
80
+
81
+ Args:
82
+ timeout: Maximum number of seconds to wait
83
+ for the process to terminate
84
+
85
+ """
86
+ import asyncio
87
+
88
+ process = self.proc
89
+ try:
90
+ process.terminate()
91
+ await asyncio.wait_for(process.wait(), timeout=timeout)
92
+ except asyncio.TimeoutError:
93
+ _logger.warning(
94
+ "Termination of the MATLAB Server process timed out. Attempting to kill."
95
+ )
96
+ process.kill()
97
+ await process.wait()
98
+ _logger.debug("Killed the MATLAB process after timeout.")
99
+
100
+ def __exit__(self, exc_type, exc_value, exc_traceback):
101
+ _logger.info("Tearing down the MATLAB Server.")
102
+ self.event_loop.run_until_complete(self._terminate_process(timeout=10))
103
+ _logger.debug("Terminated the MATLAB process.")
104
+
105
+
106
+ def _send_http_get_request(uri, connection_scheme, headers, http_endpoint=""):
107
+ """Send HTTP request to matlab-proxy server.
108
+ Returns HTTP response JSON"""
109
+
110
+ request_uri = uri + http_endpoint
111
+
112
+ json_response = None
113
+ with requests.Session() as s:
114
+ retries = Retry(total=10, backoff_factor=0.1)
115
+ s.mount(f"{connection_scheme}://", HTTPAdapter(max_retries=retries))
116
+ response = s.get(request_uri, headers=headers, verify=False)
117
+ json_response = json.loads(response.text)
118
+
119
+ return json_response
120
+
121
+
122
+ def _check_matlab_status(matlab_proxy_app_fixture, status):
123
+ uri = matlab_proxy_app_fixture.url
124
+ connection_scheme = matlab_proxy_app_fixture.connection_scheme
125
+ headers = matlab_proxy_app_fixture.headers
126
+
127
+ matlab_status = None
128
+
129
+ start_time = time.time()
130
+ while matlab_status != status and (time.time() - start_time < MAX_TIMEOUT):
131
+ time.sleep(1)
132
+ res = _send_http_get_request(
133
+ uri, connection_scheme, headers, http_endpoint="/get_status"
134
+ )
135
+ matlab_status = res["matlab"]["status"]
136
+
137
+ return matlab_status
138
+
139
+
140
+ @pytest.fixture
141
+ def matlab_proxy_app_fixture(
142
+ loop,
143
+ ):
144
+ """A pytest fixture which yields a real matlab server to be used by tests.
145
+
146
+ Args:
147
+ loop (Event event_loop): The built-in event event_loop provided by pytest.
148
+
149
+ Yields:
150
+ real_matlab_server : A real matlab web server used by tests.
151
+ """
152
+
153
+ try:
154
+ with RealMATLABServer(loop) as matlab_proxy_app:
155
+ yield matlab_proxy_app
156
+ except ProcessLookupError as e:
157
+ _logger.debug("ProcessLookupError found in matlab proxy app fixture")
158
+ _logger.debug(e)
159
+ pass
160
+
161
+
162
+ def test_matlab_is_up(matlab_proxy_app_fixture):
163
+ """Test that the status switches from 'starting' to 'up' within a timeout.
164
+
165
+ Args:
166
+ matlab_proxy_app_fixture: A pytest fixture which yields a real matlab server to be used by tests.
167
+ """
168
+
169
+ status = _check_matlab_status(matlab_proxy_app_fixture, "up")
170
+ assert status == "up"
171
+
172
+
173
+ def test_stop_matlab(matlab_proxy_app_fixture):
174
+ """Test to check that matlab is in 'down' state when
175
+ we send the delete request to 'stop_matlab' endpoint
176
+
177
+ Args:
178
+ matlab_proxy_app_fixture: A pytest fixture which yields a real matlab server to be used by tests.
179
+ """
180
+ status = _check_matlab_status(matlab_proxy_app_fixture, "up")
181
+ assert status == "up"
182
+
183
+ http_endpoint_to_test = "/stop_matlab"
184
+ stop_url = matlab_proxy_app_fixture.url + http_endpoint_to_test
185
+
186
+ with requests.Session() as s:
187
+ retries = Retry(total=10, backoff_factor=0.1)
188
+ s.mount(
189
+ f"{matlab_proxy_app_fixture.connection_scheme}://",
190
+ HTTPAdapter(max_retries=retries),
191
+ )
192
+ s.delete(stop_url, headers=matlab_proxy_app_fixture.headers, verify=False)
193
+
194
+ status = _check_matlab_status(matlab_proxy_app_fixture, "down")
195
+ assert status == "down"
196
+
197
+
198
+ # FIXME: If output has logging or extra debug info, 600 bytes might not be enough.
199
+ async def test_print_message(matlab_proxy_app_fixture):
200
+ """Test if the right logs are printed
201
+
202
+ Args:
203
+ matlab_proxy_app_fixture: A pytest fixture which yields a real matlab server to be used by tests.
204
+
205
+ """
206
+ # Checks if matlab proxy is in "up" state or not
207
+ status = _check_matlab_status(matlab_proxy_app_fixture, "up")
208
+ assert status == "up"
209
+
210
+ uri_regex = f"{matlab_proxy_app_fixture.connection_scheme}://[a-zA-Z0-9\-_.]+:{matlab_proxy_app_fixture.mwi_app_port}{matlab_proxy_app_fixture.mwi_base_url}"
211
+
212
+ read_descriptor, write_descriptor = matlab_proxy_app_fixture.dpipe
213
+ number_of_bytes = 600
214
+
215
+ if read_descriptor:
216
+ line = os.read(read_descriptor, number_of_bytes).decode("utf-8")
217
+ process_logs = line.strip()
218
+
219
+ assert bool(re.search(uri_regex, process_logs)) == True
220
+
221
+ # Close the read and write descriptors.
222
+ os.close(read_descriptor)
223
+ os.close(write_descriptor)
@@ -0,0 +1 @@
1
+ # Copyright 2023 The MathWorks, Inc.