From 9cd9f53a48ab87774606a37b426bd83ac7be075a Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 13 Jan 2025 14:57:22 -0600 Subject: [PATCH 1/4] add poster option that raises an exception --- src/ansys/mechanical/core/embedding/poster.py | 26 ++++++++++++++++++- tests/embedding/test_app.py | 15 ++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/ansys/mechanical/core/embedding/poster.py b/src/ansys/mechanical/core/embedding/poster.py index 93a994cc0..405f0aea4 100644 --- a/src/ansys/mechanical/core/embedding/poster.py +++ b/src/ansys/mechanical/core/embedding/poster.py @@ -25,6 +25,14 @@ import typing +class PosterError(Exception): + def __init__(self, error: Exception): + self._error = error + + @property + def error(self) -> Exception: + return self._error + class Poster: """Class which can post a python callable function to Mechanical's main thread.""" @@ -37,7 +45,23 @@ def __init__(self): self._poster = Ans.Common.WB1ManagedUtils.TaskPoster - def post(self, callable: typing.Callable): + def try_post(self, callable: typing.Callable) -> typing.Any: + """Same as `post`, but raises exceptions. + + If `callable` raises an exception, try_post will raise + the same exception to the caller of try_post. + """ + def wrapped(): + try: + return callable() + except Exception as e: + return PosterError(e) + result = self.post(wrapped) + if isinstance(result, PosterError): + raise result.error + return result + + def post(self, callable: typing.Callable) -> typing.Any: """Post the callable to Mechanical's main thread. The main thread needs to be receiving posted messages diff --git a/tests/embedding/test_app.py b/tests/embedding/test_app.py index 4d4f01a90..910d83c8d 100644 --- a/tests/embedding/test_app.py +++ b/tests/embedding/test_app.py @@ -169,6 +169,7 @@ def test_app_poster(embedded_app): poster = embedded_app.poster name = [] + error = [] def change_name_async(poster): """Change_name_async will run a background thread @@ -182,9 +183,19 @@ def get_name(): def change_name(): embedded_app.DataModel.Project.Name = "foo" + def raise_ex(): + raise Exception("Exception") + name.append(poster.post(get_name)) poster.post(change_name) + try: + poster.try_post() + except Exception as e: + error.append(e) + + name.append(poster.try_post(get_name)) + import threading change_name_thread = threading.Thread(target=change_name_async, args=(poster,)) @@ -196,9 +207,11 @@ def change_name(): # thread, e.g. `change_name` that was posted by the poster. utils.sleep(400) change_name_thread.join() - assert len(name) == 1 + assert len(name) == 2 assert name[0] == "Project" + assert name[1] == "foo" assert embedded_app.DataModel.Project.Name == "foo" + assert len(error) == 1 @pytest.mark.embedding From f300054c20e80b131d10e1ca994a875cef5fb693 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:57:46 +0000 Subject: [PATCH 2/4] chore: auto fixes from pre-commit hooks --- src/ansys/mechanical/core/embedding/poster.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ansys/mechanical/core/embedding/poster.py b/src/ansys/mechanical/core/embedding/poster.py index 405f0aea4..f6f0e2c98 100644 --- a/src/ansys/mechanical/core/embedding/poster.py +++ b/src/ansys/mechanical/core/embedding/poster.py @@ -33,6 +33,7 @@ def __init__(self, error: Exception): def error(self) -> Exception: return self._error + class Poster: """Class which can post a python callable function to Mechanical's main thread.""" @@ -51,11 +52,13 @@ def try_post(self, callable: typing.Callable) -> typing.Any: If `callable` raises an exception, try_post will raise the same exception to the caller of try_post. """ + def wrapped(): try: return callable() except Exception as e: return PosterError(e) + result = self.post(wrapped) if isinstance(result, PosterError): raise result.error From 3357de7edc5a4497f441658abc785c72d43d370d Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Mon, 13 Jan 2025 21:01:34 +0000 Subject: [PATCH 3/4] chore: adding changelog file 1038.added.md [dependabot-skip] --- doc/changelog.d/1038.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/1038.added.md diff --git a/doc/changelog.d/1038.added.md b/doc/changelog.d/1038.added.md new file mode 100644 index 000000000..093e54d4f --- /dev/null +++ b/doc/changelog.d/1038.added.md @@ -0,0 +1 @@ +add poster method that raises an exception \ No newline at end of file From 9be6b5ae2f5f1fe8c76f117213db284e4aff1e8c Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Mon, 13 Jan 2025 15:03:36 -0600 Subject: [PATCH 4/4] style --- src/ansys/mechanical/core/embedding/poster.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ansys/mechanical/core/embedding/poster.py b/src/ansys/mechanical/core/embedding/poster.py index f6f0e2c98..c9ccd1ae8 100644 --- a/src/ansys/mechanical/core/embedding/poster.py +++ b/src/ansys/mechanical/core/embedding/poster.py @@ -26,11 +26,15 @@ class PosterError(Exception): + """Class which holds errors from the background thread posting system.""" + def __init__(self, error: Exception): + """Create an instance to hold the given error.""" self._error = error @property def error(self) -> Exception: + """Get the underlying exception.""" return self._error @@ -47,10 +51,11 @@ def __init__(self): self._poster = Ans.Common.WB1ManagedUtils.TaskPoster def try_post(self, callable: typing.Callable) -> typing.Any: - """Same as `post`, but raises exceptions. + """Post the callable to Mechanical's main thread. - If `callable` raises an exception, try_post will raise - the same exception to the caller of try_post. + This does the same thing as `post` but if `callable` + raises an exception, try_post will raise the same + exception to the caller of `try_post`. """ def wrapped():