Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ jobs:
- name: Install and Test with pytest
run: |
python -m pip install -e .[Dev]
pytest tests/ --cov=${{ github.event.repository.name }} --cov-report=html:htmlcov --cov-report=term
pytest tests/ --cov=RATpy --cov-report=term
33 changes: 24 additions & 9 deletions RATpy/wrappers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pathlib
from contextlib import suppress
from typing import Callable, Tuple

import numpy as np
Expand All @@ -7,6 +8,24 @@
import RATpy.rat_core


def start_matlab():
"""Starts MATLAB asynchronously and returns a future to retrieve the engine later

Returns
-------
future : matlab.engine.futureresult.FutureResult
A future used to get the actual matlab engine

"""
future = None
with suppress(ImportError):
import matlab.engine

future = matlab.engine.start_matlab(background=True)

return future


class MatlabWrapper:
"""Creates a python callback for a MATLAB function.

Expand All @@ -17,21 +36,17 @@ class MatlabWrapper:

"""

loader = start_matlab()

def __init__(self, filename: str) -> None:
self.engine = None
try:
import matlab.engine
except ImportError:
if self.loader is None:
raise ImportError("matlabengine is required to use MatlabWrapper") from None
self.engine = matlab.engine.start_matlab()

self.engine = self.loader.result()
path = pathlib.Path(filename)
self.engine.cd(str(path.parent), nargout=0)
self.function_name = path.stem

def __del__(self):
if self.engine is not None:
self.engine.quit()

def getHandle(self) -> Callable[[ArrayLike, ArrayLike, ArrayLike, int, int], Tuple[ArrayLike, float]]:
"""Returns a wrapper for the custom MATLAB function

Expand Down
1 change: 0 additions & 1 deletion requirements-dev.txt

This file was deleted.

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ pytest >= 7.4.0
pytest-cov >= 4.1.0
matplotlib >= 3.8.3
StrEnum >= 0.4.15; python_version < '3.11'
ruff >= 0.4.10
25 changes: 13 additions & 12 deletions tests/test_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,13 +618,14 @@ def test_make_input(test_project, test_problem, test_cells, test_limits, test_pr
"domainRatio",
]

mocked_matlab_module = mock.MagicMock()
mocked_matlab_future = mock.MagicMock()
mocked_engine = mock.MagicMock()
mocked_matlab_module.engine.start_matlab.return_value = mocked_engine
mocked_matlab_future.result.return_value = mocked_engine

with mock.patch.dict(
"sys.modules",
{"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine},
with mock.patch.object(
RATpy.wrappers.MatlabWrapper,
"loader",
mocked_matlab_future,
), mock.patch.object(RATpy.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object(
RATpy.inputs,
"get_python_handle",
Expand Down Expand Up @@ -757,13 +758,13 @@ def test_make_cells(test_project, test_cells, request) -> None:
test_project = request.getfixturevalue(test_project)
test_cells = request.getfixturevalue(test_cells)

mocked_matlab_module = mock.MagicMock()
mocked_matlab_engine = mock.MagicMock()
mocked_matlab_module.engine.start_matlab.return_value = mocked_matlab_engine

with mock.patch.dict(
"sys.modules",
{"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine},
mocked_matlab_future = mock.MagicMock()
mocked_engine = mock.MagicMock()
mocked_matlab_future.result.return_value = mocked_engine
with mock.patch.object(
RATpy.wrappers.MatlabWrapper,
"loader",
mocked_matlab_future,
), mock.patch.object(RATpy.rat_core, "DylibEngine", mock.MagicMock()), mock.patch.object(
RATpy.inputs,
"get_python_handle",
Expand Down
13 changes: 7 additions & 6 deletions tests/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@


def test_matlab_wrapper() -> None:
with mock.patch.dict("sys.modules", {"matlab": mock.MagicMock(side_effect=ImportError)}), pytest.raises(
ImportError,
with (
mock.patch.object(RATpy.wrappers.MatlabWrapper, "loader", None),
pytest.raises(ImportError),
):
RATpy.wrappers.MatlabWrapper("demo.m")
mocked_matlab_module = mock.MagicMock()
mocked_engine = mock.MagicMock()
mocked_matlab_module.engine.start_matlab.return_value = mocked_engine

with mock.patch.dict("sys.modules", {"matlab": mocked_matlab_module, "matlab.engine": mocked_matlab_module.engine}):
mocked_matlab_future = mock.MagicMock()
mocked_engine = mock.MagicMock()
mocked_matlab_future.result.return_value = mocked_engine
with mock.patch.object(RATpy.wrappers.MatlabWrapper, "loader", mocked_matlab_future):
wrapper = RATpy.wrappers.MatlabWrapper("demo.m")
assert wrapper.function_name == "demo"
mocked_engine.cd.assert_called_once()
Expand Down