Skip to content

Commit c8644e3

Browse files
committed
R2022b 9.13.1a0
1 parent a62dfe5 commit c8644e3

File tree

4 files changed

+116
-91
lines changed

4 files changed

+116
-91
lines changed

.github/workflows/python-publish.yml

+10-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,17 @@ jobs:
2626
- name: Build package
2727
run: python setup.py sdist
2828

29-
- name: Publish package
29+
- name: Publish package to TestPyPI since the "prerelease" checkbox is checked
30+
if: "github.event.release.prerelease"
3031
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
3132
with:
3233
user: __token__
3334
password: ${{ secrets.MATLABENGINE_TEST_PYPI_TOKEN }}
35+
repository_url: https://test.pypi.org/legacy/
36+
37+
- name: Publish package to PyPI since the "prerelease" checkbox is unchecked
38+
if: "!github.event.release.prerelease"
39+
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
40+
with:
41+
user: __token__
42+
password: ${{ secrets.MATLABENGINE_PYPI_TOKEN }}

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ The MATLAB® Engine API for Python® provides a package to integrate MATLA
66
## Requirements
77
### Required MathWorks Products
88
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
9-
* MATLAB release R2022a
9+
* MATLAB release R2022b
1010

1111
### Required 3rd Party Products
1212
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
13-
* Python 3.8 or 3.9
13+
* Python 3.8, 3.9, or 3.10
1414
* Supported Python versions by MATLAB release can be found [here](https://www.mathworks.com/content/dam/mathworks/mathworks-dot-com/support/sysreq/files/python-compatibility.pdf).
1515

1616
---
@@ -21,15 +21,15 @@ The MATLAB&reg; Engine API for Python&reg; provides a package to integrate MATLA
2121
MATLAB Engine API for Python can be installed directly from the Python Package Index.
2222
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
2323
```bash
24-
$ python -m pip install matlabengine==9.12
24+
$ python -m pip install matlabengine==9.13.1a0
2525
```
2626

2727

2828

2929
### Linux&reg;
3030
Prior to installation, check the default install location of MATLAB by calling ```matlabroot``` in a MATLAB Command Window. By default, Linux installs MATLAB at:<br>
3131
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
32-
```/usr/local/MATLAB/R2022a```
32+
```/usr/local/MATLAB/R2022b```
3333

3434
When MATLAB is not installed in the default location, the bin/*architecture* directory within the MATLAB root directory must be added to an environment variable. The path can be added to the environment variable within the shell startup configuration file (for example, .bashrc for bash shell or .tcshrc for tcsh).
3535

@@ -46,14 +46,14 @@ setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:matlabroot/bin/glnxa64
4646
MATLAB Engine API for Python can be installed directly from the Python Package Index.
4747
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
4848
```bash
49-
$ python -m pip install matlabengine==9.12
49+
$ python -m pip install matlabengine==9.13.1a0
5050
```
5151

5252
### macOS
5353
Prior to installation, check the default install location of MATLAB by calling ```matlabroot``` in a MATLAB Command Window. By default, macOS installs MATLAB at:<br>
5454

5555
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
56-
```/Applications/MATLAB_R2022a.app```
56+
```/Applications/MATLAB_R2022b.app```
5757

5858
When MATLAB is not installed in the default location, the bin/*architecture* directory within the MATLAB root directory must be added to an environment variable. The path can be added to the environment variable within the shell startup configuration file (for example, .bashrc for bash shell or .tcshrc for tcsh).
5959

@@ -70,7 +70,7 @@ setenv DYLD_LIBRARY_PATH ${DYLD_LIBRARY_PATH}:matlabroot/bin/maci64
7070
MATLAB Engine API for Python can be installed directly from the Python Package Index.
7171
<!-- MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string) -->
7272
```bash
73-
$ python -m pip install matlabengine==9.12
73+
$ python -m pip install matlabengine==9.13.1a0
7474
```
7575

7676
---

setup.py

+54-28
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from setuptools import setup, find_packages
44
from setuptools.command.build_py import build_py
55
import os
6+
import re
67
import sys
78
import platform
89
import xml.etree.ElementTree as xml
@@ -20,23 +21,21 @@ class _MatlabFinder(build_py):
2021
}
2122

2223
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
23-
MATLAB_REL = 'R2022a'
24+
MATLAB_REL = 'R2022b'
2425

2526
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
26-
MATLAB_VER = '9.12'
27+
MATLAB_VER = '9.13.1a0'
2728

2829
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
29-
SUPPORTED_PYTHON_VERSIONS = set(['3.8', '3.9'])
30+
SUPPORTED_PYTHON_VERSIONS = set(['3.8', '3.9', '3.10'])
3031

3132
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
3233
VER_TO_REL = {
33-
"9.6": "R2019a",
34-
"9.7": "R2019b",
35-
"9.8": "R2020a",
3634
"9.9": "R2020b",
3735
"9.10": "R2021a",
3836
"9.11": "R2021b",
39-
"9.12": "R2022a"
37+
"9.12": "R2022a",
38+
"9.13": "R2022b"
4039
}
4140

4241
DEFAULT_INSTALLS = {
@@ -51,7 +50,8 @@ class _MatlabFinder(build_py):
5150
found_matlab = ''
5251

5352
# ERROR MESSAGES
54-
minimum_required = "No compatible version of MATLAB was found. This feature supports MATLAB R2019a and later."
53+
minimum_maximum = "No compatible version of MATLAB was found. " + \
54+
"This feature supports MATLAB {min_v:s} ({min_r:s}) through {max_v:s} ({max_r:s}), inclusive."
5555
dir_not_found = "Directory not found: "
5656
install_compatible = "To install a compatible version, call python -m pip install matlabengine=="
5757
no_windows_install = "MATLAB installation not found in Windows Registry:"
@@ -60,9 +60,11 @@ class _MatlabFinder(build_py):
6060
set_path = "MATLAB installation not found in {path1:s}. Add matlabroot/bin/{arch:s} to {path2:s}."
6161
no_compatible_matlab = "No compatible MATLAB installation found in Windows Registry. This release of " + \
6262
"MATLAB Engine API for Python is compatible with version {ver:s}. The found versions were"
63-
no_matlab = "No MATLAB installation found in Windows Registry."
63+
no_matlab = "No compatible MATLAB installation found in Windows Registry."
6464
incompatible_ver = "MATLAB version {ver:s} was found, but MATLAB Engine API for Python is not compatible with it. " + \
6565
"To install a compatible version, call python -m pip install matlabengine=={found:s}."
66+
invalid_version_from_matlab_ver = "Format of MATLAB version '{ver:s}' is invalid."
67+
invalid_version_from_eng = "Format of MATLAB Engine API version '{ver:s}' is invalid."
6668

6769
def set_platform_and_arch(self):
6870
"""
@@ -168,26 +170,46 @@ def _find_matlab_key_from_windows_registry(self, key):
168170
found_vers = []
169171
for idx in range(num_keys):
170172
sub_key = winreg.EnumKey(key, idx)
171-
found_vers.append(sub_key)
172-
# Example: the version in the registry could be "9.13.1" whereas our version is "9.13"
173-
# we still want to allow this
174-
if sub_key.startswith(self.MATLAB_VER):
175-
key_value = sub_key
176-
break
173+
if sub_key in self.VER_TO_REL:
174+
found_vers.append(sub_key)
175+
# Example: the version in the registry could be "9.X" whereas the version in this file could be "9.X.Y".
176+
# We want to allow this.
177+
if self._check_matlab_ver_against_engine(sub_key):
178+
key_value = sub_key
179+
break
177180

178181
if not key_value:
179182
if found_vers:
180183
vers = ', '.join(found_vers)
181-
raise RuntimeError(f"{self.no_compatible_matlab.format(ver=self.MATLAB_VER)} {vers}. {self.install_compatible}{found_vers[-1]}.")
184+
eng_ver_major_minor = self._get_engine_ver_major_minor()
185+
eng_ver_major_minor_as_str = '{}.{}'.format(eng_ver_major_minor[0], eng_ver_major_minor[1])
186+
raise RuntimeError(f"{self.no_compatible_matlab.format(ver=eng_ver_major_minor_as_str)} {vers}. {self.install_compatible}{found_vers[-1]}.")
182187
else:
183188
raise RuntimeError(f"{self.no_matlab}")
184189

185190
return key_value
186191

192+
def _get_engine_ver_major_minor(self):
193+
re_major_minor = "^(\d+)\.(\d+)"
194+
eng_match = re.match(re_major_minor, self.MATLAB_VER)
195+
if not eng_match:
196+
raise RuntimeError(f"{self.invalid_version_from_eng.format(ver=self.MATLAB_VER)}")
197+
return (eng_match.group(1), eng_match.group(2))
198+
199+
def _check_matlab_ver_against_engine(self, matlab_ver):
200+
re_major_minor = "^(\d+)\.(\d+)"
201+
matlab_ver_match = re.match(re_major_minor, matlab_ver)
202+
if not matlab_ver_match:
203+
raise RuntimeError(f"{self.invalid_version_from_matlab_ver.format(ver=matlab_ver)}")
204+
eng_major_minor = self._get_engine_ver_major_minor()
205+
matlab_ver_major_minor = (matlab_ver_match.group(1), matlab_ver_match.group(2))
206+
return (matlab_ver_major_minor == eng_major_minor)
207+
187208
def verify_matlab_release(self, root):
188209
"""
189210
Parses VersionInfo.xml to verify the MATLAB release matches the supported release
190-
for the Python Engine.
211+
for the Python Engine. The major and minor version numbers must match. Everything
212+
else will be ignored.
191213
"""
192214
version_info = os.path.join(root, 'VersionInfo.xml')
193215
if not os.path.isfile(version_info):
@@ -201,10 +223,7 @@ def verify_matlab_release(self, root):
201223
if child.tag == 'release':
202224
matlab_release = self.found_matlab = child.text
203225
break
204-
205-
if matlab_release != self.MATLAB_REL:
206-
return False
207-
return True
226+
return matlab_release == self.MATLAB_REL
208227

209228
def search_path_for_directory_unix(self):
210229
"""
@@ -225,8 +244,8 @@ def search_path_for_directory_unix(self):
225244
while not matlab_root and ending_idx < len(endings):
226245
ending = endings[ending_idx]
227246
if path.endswith(ending):
228-
# _get_matlab_root_from_unix_bin will return an empty string if MATLAB is not found
229-
# non-empty string (MATLAB found) will break both loops
247+
# _get_matlab_root_from_unix_bin will return an empty string if MATLAB is not found.
248+
# Non-empty string (MATLAB found) will break both loops.
230249
matlab_root = self._get_matlab_root_from_unix_bin(path)
231250
ending_idx += 1
232251
dir_idx += 1
@@ -235,9 +254,15 @@ def search_path_for_directory_unix(self):
235254
if self.found_matlab:
236255
if self.found_matlab in self.VER_TO_REL:
237256
raise RuntimeError(self.incompatible_ver.format(ver=self.VER_TO_REL[self.found_matlab], found=self.found_matlab))
238-
# we found a MATLAB release but it is older than R2019a
257+
# We found a MATLAB release but it is older than the oldest version we support,
258+
# or newer than the newest version we support.
239259
else:
240-
raise RuntimeError(self.minimum_required)
260+
v_to_r_keys = list(self.VER_TO_REL.keys())
261+
min_v = v_to_r_keys[0]
262+
min_r = self.VER_TO_REL[min_v]
263+
max_v = v_to_r_keys[-1]
264+
max_r = self.VER_TO_REL[max_v]
265+
raise RuntimeError(self.minimum_maximum.format(min_v=min_v, min_r=min_r, max_v=max_v, max_r=max_r))
241266
else:
242267
raise RuntimeError(self.set_path.format(path1=self.path_name, arch=self.arch, path2=self.path_name))
243268

@@ -284,7 +309,7 @@ def run(self):
284309
setup(
285310
name="matlabengine",
286311
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
287-
version="9.12",
312+
version="9.13.1a0",
288313
description='A module to call MATLAB from Python',
289314
author='MathWorks',
290315
license="MathWorks XSLA License",
@@ -310,8 +335,9 @@ def run(self):
310335
"Intended Audience :: Developers",
311336
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
312337
"Programming Language :: Python :: 3.8",
313-
"Programming Language :: Python :: 3.9"
338+
"Programming Language :: Python :: 3.9",
339+
"Programming Language :: Python :: 3.10"
314340
],
315341
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
316-
python_requires=">=3.8, <3.10"
342+
python_requires=">=3.8, <3.11"
317343
)

src/matlab/engine/__init__.py

+45-55
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2022 MathWorks, Inc.
1+
#Copyright 2014-2022 MathWorks, Inc.
22

33
"""
44
The MATLAB Engine enables you to call any MATLAB statement either synchronously
@@ -19,73 +19,63 @@
1919
"""
2020

2121

22+
import os
2223
import sys
2324
import importlib
2425
import atexit
26+
import weakref
2527
import threading
26-
import platform
27-
import os
28-
29-
package_folder = os.path.dirname(os.path.realpath(__file__))
30-
31-
def add_dirs_to_path(bin_dir, engine_dir, extern_dir):
32-
"""
33-
Adds MATLAB engine and extern/bin directories to sys.path.
34-
"""
35-
path = 'PATH'
36-
37-
if not os.path.isdir(engine_dir):
38-
raise RuntimeError("Could not find directory: {0}".format(engine_dir))
39-
40-
if not os.path.isdir(extern_dir):
41-
raise RuntimeError("Could not find directory: {0}".format(extern_dir))
42-
43-
if platform.system() == 'Windows':
44-
if not os.path.isdir(bin_dir):
45-
raise RuntimeError("Could not find directory: {0}".format(bin_dir))
46-
if path in os.environ:
47-
paths = os.environ[path]
48-
os.environ[path] = bin_dir + os.pathsep + paths
49-
else:
50-
os.environ[path] = bin_dir
51-
if sys.version_info.major >= 3 and sys.version_info.minor >= 8:
52-
os.add_dll_directory(bin_dir)
53-
54-
sys.path.insert(0, engine_dir)
55-
sys.path.insert(0, extern_dir)
5628

57-
# MUST_BE_UPDATED_EACH_RELEASE (Search repo for this string)
58-
_supported_versions = set(['3_8', '3_9'])
29+
# UPDATE_IF_PYTHON_VERSION_ADDED_OR_REMOVED : search for this string in codebase
30+
# when support for a Python version must be added or removed
31+
_supported_versions = ['2_7', '3_8', '3_9', '3_10']
5932
_ver = sys.version_info
6033
_version = '{0}_{1}'.format(_ver[0], _ver[1])
61-
if _version not in _supported_versions:
62-
raise RuntimeError("Python {0}.{1} is not supported. Supported versions " +
63-
'are {2}.'.format(_ver[0], _ver[1, _supported_versions]))
64-
65-
first_exception_message = ''
66-
second_exception_message = ''
34+
_PYTHONVERSION = None
35+
36+
if _version in _supported_versions:
37+
_PYTHONVERSION = _version
38+
else:
39+
raise EnvironmentError("Python %s is not supported." % _version)
40+
41+
_module_folder = os.path.dirname(os.path.realpath(__file__))
42+
_arch_filename = os.path.join(_module_folder, "_arch.txt")
43+
success = False
44+
firstExceptionMessage = ''
45+
secondExceptionMessage = ''
6746
try:
68-
pythonengine = importlib.import_module("matlabengineforpython"+_version)
69-
except Exception as first_error:
70-
first_exception_message = str(first_error)
47+
pythonengine = importlib.import_module("matlabengineforpython"+_PYTHONVERSION)
48+
except Exception as firstE:
49+
firstExceptionMessage = str(firstE)
7150

72-
if first_exception_message:
51+
if firstExceptionMessage:
7352
try:
74-
arch_file = os.path.join(package_folder, '_arch.txt')
75-
with open(arch_file, 'r') as root:
76-
[arch, bin_folder, engine_folder, extern_bin] = [line.strip() for line in root.readlines()]
77-
78-
add_dirs_to_path(bin_folder, engine_folder, extern_bin)
79-
pythonengine = importlib.import_module("matlabengineforpython"+_version)
80-
81-
except Exception as second_error:
53+
_arch_file = open(_arch_filename,'r')
54+
_lines = _arch_file.readlines()
55+
[_arch, _bin_dir,_engine_dir, _extern_bin_dir] = [x.rstrip() for x in _lines if x.rstrip() != ""]
56+
_arch_file.close()
57+
sys.path.insert(0,_engine_dir)
58+
sys.path.insert(0,_extern_bin_dir)
59+
60+
_envs = {'win32': 'PATH', 'win64': 'PATH'}
61+
if _arch in _envs:
62+
if _envs[_arch] in os.environ:
63+
_env = os.environ[_envs[_arch]]
64+
os.environ[_envs[_arch]] = _bin_dir + os.pathsep + os.environ[_envs[_arch]]
65+
else:
66+
os.environ[_envs[_arch]] = _bin_dir
67+
if sys.version_info.major >= 3 and sys.version_info.minor >= 8:
68+
os.add_dll_directory(_bin_dir)
69+
pythonengine = importlib.import_module("matlabengineforpython"+_PYTHONVERSION)
70+
except Exception as secondE:
8271
str1 = 'Please reinstall MATLAB Engine for Python or contact '
8372
str2 = 'MathWorks Technical Support for assistance:\nFirst issue: {}\nSecond issue: {}'.format(
84-
first_exception_message, second_error)
85-
second_exception_message = str1 + str2
73+
firstExceptionMessage, secondE)
74+
secondExceptionMessage = str1 + str2
75+
76+
if secondExceptionMessage:
77+
raise EnvironmentError(secondExceptionMessage)
8678

87-
if second_exception_message:
88-
raise EnvironmentError(second_exception_message)
8979

9080
"""
9181
This lock can make sure the global variable _engines is updated correctly in

0 commit comments

Comments
 (0)