From c506eb4773f359f16c0132ef6235541e206531ab Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 23 Mar 2026 20:00:40 -0500 Subject: [PATCH 1/5] add reuse flag to overrrider gallery flag --- doc/source/conf.py | 3 +- doc/source/user_guide/howto/globals.rst | 19 ++++++++++ src/ansys/mechanical/core/__init__.py | 14 ++++++- src/ansys/mechanical/core/embedding/app.py | 16 +++++++- tests/embedding/test_app.py | 13 ++++++- tests/embedding/test_globals.py | 1 + tests/scripts/reuse_instance_test.py | 43 ++++++++++++++++++++++ 7 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 tests/scripts/reuse_instance_test.py diff --git a/doc/source/conf.py b/doc/source/conf.py index 2665ac0d4b..86aecd0742 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -22,7 +22,8 @@ import ansys.mechanical.core as pymechanical from ansys.mechanical.core.embedding.initializer import SUPPORTED_MECHANICAL_EMBEDDING_VERSIONS -# necessary when building the sphinx gallery +# Documentation gallery: enables Sphinx-Gallery and embedded ``App`` instance +# reuse across gallery scripts. Per-constructor opt-out: ``App(..., reuse_instance=True)``. pymechanical.BUILDING_GALLERY = True # Ensure that offscreen rendering is used for docs generation diff --git a/doc/source/user_guide/howto/globals.rst b/doc/source/user_guide/howto/globals.rst index 6d425defd0..0d5e25685b 100644 --- a/doc/source/user_guide/howto/globals.rst +++ b/doc/source/user_guide/howto/globals.rst @@ -43,3 +43,22 @@ not for the ``globals`` argument of the ``App`` class: app = App() app.update_globals(globals(), False) + +Documentation gallery and ``BUILDING_GALLERY`` +----------------------------------------------- + +Building the HTML documentation sets the module flag ``BUILDING_GALLERY`` so that +Sphinx-Gallery can run examples and so that multiple embedded ``App()`` +calls in those examples share one Mechanical instance. If you need one +construction of ``App`` to behave as if ``BUILDING_GALLERY`` were ``False`` +(for example to avoid sharing while the flag remains ``True`` globally), pass +``reuse_instance=True``: + +.. code:: python + + import ansys.mechanical.core as pymechanical + + app = pymechanical.App(globals=globals(), reuse_instance=True) + +See also :py:data:`~ansys.mechanical.core.BUILDING_GALLERY` and +:class:`~ansys.mechanical.core.embedding.app.App`. diff --git a/src/ansys/mechanical/core/__init__.py b/src/ansys/mechanical/core/__init__.py index a6da4c7426..82b649ec65 100644 --- a/src/ansys/mechanical/core/__init__.py +++ b/src/ansys/mechanical/core/__init__.py @@ -76,4 +76,16 @@ from ansys.mechanical.core.pool import LocalMechanicalPool BUILDING_GALLERY = False -"""Whether or not to build gallery examples.""" +"""Control documentation gallery behavior and embedded-app instance sharing. + +When ``True``: + +- Sphinx enables the example gallery during documentation builds (see ``doc/source/conf.py``). +- For the embedded :class:`~ansys.mechanical.core.embedding.app.App`, multiple + ``App()`` constructions reuse one underlying Mechanical instance so examples can + run without exhausting resources. + +To opt out of embedded instance sharing for a single ``App`` while leaving this +flag unchanged (for example when ``BUILDING_GALLERY`` is set globally), pass +``reuse_instance=True`` to the constructor. +""" diff --git a/src/ansys/mechanical/core/embedding/app.py b/src/ansys/mechanical/core/embedding/app.py index afe6a93917..ed1513c724 100644 --- a/src/ansys/mechanical/core/embedding/app.py +++ b/src/ansys/mechanical/core/embedding/app.py @@ -180,6 +180,13 @@ class App: feature_flags : list, optional List of feature flag names to enable. Default is []. Available flags include: 'ThermalShells', 'MultistageHarmonic', 'CPython'. + reuse_instance : bool, optional + When ``True``, gallery instance sharing is skipped for this constructor, + so initialization follows the same path as when the module-level + ``BUILDING_GALLERY`` flag is ``False``. Use this to opt out of gallery + sharing without assigning ``pymechanical.BUILDING_GALLERY = False`` (for + example when the flag is set globally for documentation builds). + Default is ``False``. Examples -------- @@ -224,12 +231,16 @@ def __init__( self, db_file: str | None = None, private_appdata: bool = False, + *, + reuse_instance: bool = False, **kwargs: typing.Any, ) -> None: """Construct an instance of the mechanical Application.""" global INSTANCES from ansys.mechanical.core import BUILDING_GALLERY + use_gallery_sharing = BUILDING_GALLERY and not reuse_instance + self._enable_logging = kwargs.get("enable_logging", True) if self._enable_logging: self._log = LOG @@ -258,7 +269,7 @@ def __init__( # If the building gallery flag is set, we need to share the instance # This can apply to running the `make -C doc html` command - if BUILDING_GALLERY: + if use_gallery_sharing: if len(INSTANCES) != 0: # Get the first instance of the app instance: App = INSTANCES[0] @@ -642,7 +653,8 @@ def _share(self, other) -> None: """Shares the state of self with other. Other is another instance of App. - This is used when the BUILDING_GALLERY flag is on. + This is used when the BUILDING_GALLERY flag is on and the constructor + was not called with ``reuse_instance=True``. In that mode, multiple instance of App are used, but they all point to the same underlying application object. Because of that, special care needs to be diff --git a/tests/embedding/test_app.py b/tests/embedding/test_app.py index 175adeb095..f1aae39d99 100644 --- a/tests/embedding/test_app.py +++ b/tests/embedding/test_app.py @@ -312,7 +312,8 @@ def test_building_gallery(pytestconfig, run_subprocess, rootdir): """Test for building gallery check. When building the gallery, each example file creates another instance of the app. - When the BUILDING_GALLERY flag is enabled, only one instance is kept. + When the BUILDING_GALLERY flag is enabled, only one instance is kept (unless a + constructor uses ``reuse_instance=True`` to opt out of sharing). This is to test the bug fixed in https://github.com/ansys/pymechanical/pull/784 and will fail on PyMechanical version 0.11.0 """ @@ -337,6 +338,16 @@ def test_building_gallery(pytestconfig, run_subprocess, rootdir): assert "Multiple App launched with building gallery flag on" in stdout +@pytest.mark.embedding_scripts +def test_reuse_instance_bypasses_gallery_sharing(pytestconfig, run_subprocess, rootdir): + """When BUILDING_GALLERY is True, ``reuse_instance=True`` skips the sharing path.""" + version = pytestconfig.getoption("ansys_version") + script = Path(rootdir) / "tests" / "scripts" / "reuse_instance_test.py" + _process, stdout, stderr = run_subprocess([sys.executable, str(script), version]) + stdout = stdout.decode() + assert "reuse_instance bypassed gallery sharing as expected" in stdout + + @pytest.mark.embedding def test_shims_import_material(embedded_app, assets): """Test deprecation warning for shims import material.""" diff --git a/tests/embedding/test_globals.py b/tests/embedding/test_globals.py index feb50cd11d..bcdb642afa 100644 --- a/tests/embedding/test_globals.py +++ b/tests/embedding/test_globals.py @@ -110,6 +110,7 @@ def test_globals_kwarg_building_gallery(run_subprocess, pytestconfig, rootdir): Test ViewOrientationType exists and messages are printed when BUILDING_GALLERY is True and globals are updated during the app initialization. + (Gallery instance sharing can be skipped per ``App`` via ``reuse_instance=True``.) """ version = pytestconfig.getoption("ansys_version") embedded_py = Path(rootdir) / "tests" / "scripts" / "run_embedded_app.py" diff --git a/tests/scripts/reuse_instance_test.py b/tests/scripts/reuse_instance_test.py new file mode 100644 index 0000000000..de19ba96f5 --- /dev/null +++ b/tests/scripts/reuse_instance_test.py @@ -0,0 +1,43 @@ +# Copyright (C) 2022 - 2026 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Exercise App(reuse_instance=...) when BUILDING_GALLERY is True.""" + +import sys + +import ansys.mechanical.core as pymechanical + + +if __name__ == "__main__": + version = int(sys.argv[1]) + pymechanical.BUILDING_GALLERY = True + + _ = pymechanical.App(version=version) + try: + pymechanical.App(version=version, reuse_instance=True) + except RuntimeError as exc: + if "Cannot have more than one embedded mechanical instance" in str(exc): + print("reuse_instance bypassed gallery sharing as expected") + else: + raise + else: + raise AssertionError("Expected RuntimeError for second App with reuse_instance=True") From c50a66086d9df1e9e1384d39d0523b3d3a847a9f Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Tue, 24 Mar 2026 01:04:20 +0000 Subject: [PATCH 2/5] chore: adding changelog file 1564.added.md [dependabot-skip] --- doc/changelog.d/1564.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/1564.added.md diff --git a/doc/changelog.d/1564.added.md b/doc/changelog.d/1564.added.md new file mode 100644 index 0000000000..91b584000a --- /dev/null +++ b/doc/changelog.d/1564.added.md @@ -0,0 +1 @@ +Add reuse flag to override gallery flag From abfa8ff426105b880a537c69288c9cf0584578d2 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 6 Apr 2026 09:46:37 -0500 Subject: [PATCH 3/5] -m review suggestions --- doc/source/user_guide/howto/globals.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/source/user_guide/howto/globals.rst b/doc/source/user_guide/howto/globals.rst index 0d5e25685b..b40893e258 100644 --- a/doc/source/user_guide/howto/globals.rst +++ b/doc/source/user_guide/howto/globals.rst @@ -60,5 +60,3 @@ construction of ``App`` to behave as if ``BUILDING_GALLERY`` were ``False`` app = pymechanical.App(globals=globals(), reuse_instance=True) -See also :py:data:`~ansys.mechanical.core.BUILDING_GALLERY` and -:class:`~ansys.mechanical.core.embedding.app.App`. From bb66673b14cf534dd80ba3435a3d5c152cb636aa Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Fri, 10 Apr 2026 12:08:04 -0500 Subject: [PATCH 4/5] remvove doc from globals --- doc/source/user_guide/embedding/globals.rst | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/doc/source/user_guide/embedding/globals.rst b/doc/source/user_guide/embedding/globals.rst index b40893e258..2bc4f9bbcc 100644 --- a/doc/source/user_guide/embedding/globals.rst +++ b/doc/source/user_guide/embedding/globals.rst @@ -44,19 +44,3 @@ not for the ``globals`` argument of the ``App`` class: app = App() app.update_globals(globals(), False) -Documentation gallery and ``BUILDING_GALLERY`` ------------------------------------------------ - -Building the HTML documentation sets the module flag ``BUILDING_GALLERY`` so that -Sphinx-Gallery can run examples and so that multiple embedded ``App()`` -calls in those examples share one Mechanical instance. If you need one -construction of ``App`` to behave as if ``BUILDING_GALLERY`` were ``False`` -(for example to avoid sharing while the flag remains ``True`` globally), pass -``reuse_instance=True``: - -.. code:: python - - import ansys.mechanical.core as pymechanical - - app = pymechanical.App(globals=globals(), reuse_instance=True) - From 1efdddf9ced341a057762d0e57a1a9dea7fcfabe Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Fri, 10 Apr 2026 12:11:11 -0500 Subject: [PATCH 5/5] add a new labels --- .github/labels.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/labels.yml b/.github/labels.yml index 0a5c4e3592..e746716168 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -74,6 +74,10 @@ description: Issues fixed in Ansys Mechanical version 271 color: FFDD33 +- name: fixed-in-next-release + description: Issues fixed in the upcoming Ansys Mechanical release + color: FFEE66 + - name: 24R2 description: Bug observed in PyMechanical with Mechanical version 24R2 color: 804000