diff --git a/doc/changelog.d/49.fixed.md b/doc/changelog.d/49.fixed.md new file mode 100644 index 0000000..c975dd4 --- /dev/null +++ b/doc/changelog.d/49.fixed.md @@ -0,0 +1 @@ +Documentation issues diff --git a/doc/source/conf.py b/doc/source/conf.py index f377e60..4d594ed 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -7,8 +7,16 @@ get_version_match, ) +import ansys.tools.usdviewer as usdviewer from ansys.tools.usdviewer import __version__ +# Enable off-screen and gallery mode for the documentation build so that +# example scripts run without opening a display (mirrors PyVista's pattern). +os.environ["USD_VIEWER_OFF_SCREEN"] = "true" +os.environ["USD_VIEWER_BUILDING_GALLERY"] = "true" +usdviewer.OFF_SCREEN = True +usdviewer.BUILDING_GALLERY = True + # Project information project = "ansys-tools-usdviewer" copyright = f"(c) {datetime.now().year} ANSYS, Inc. All rights reserved" diff --git a/src/ansys/tools/usdviewer/__init__.py b/src/ansys/tools/usdviewer/__init__.py index 35e53b7..99baacd 100644 --- a/src/ansys/tools/usdviewer/__init__.py +++ b/src/ansys/tools/usdviewer/__init__.py @@ -22,5 +22,14 @@ """USD Viewer main module.""" import importlib.metadata as importlib_metadata +import os __version__ = importlib_metadata.version(__name__.replace(".", "-")) + +# When True, the viewer window is not shown. Useful for CI/CD, testing, and doc generation. +# Can be set programmatically or via the USD_VIEWER_OFF_SCREEN environment variable. +OFF_SCREEN: bool = os.environ.get("USD_VIEWER_OFF_SCREEN", "false").lower() == "true" + +# When True, indicates the viewer is being used to build a Sphinx gallery. +# Implies off-screen rendering. Can be set via the USD_VIEWER_BUILDING_GALLERY env variable. +BUILDING_GALLERY: bool = os.environ.get("USD_VIEWER_BUILDING_GALLERY", "false").lower() == "true" diff --git a/src/ansys/tools/usdviewer/viewer.py b/src/ansys/tools/usdviewer/viewer.py index c9eeb79..fa756b5 100644 --- a/src/ansys/tools/usdviewer/viewer.py +++ b/src/ansys/tools/usdviewer/viewer.py @@ -21,6 +21,8 @@ import sys import warnings +import ansys.tools.usdviewer as _usdviewer + try: from pxr import Usd, UsdUtils from pxr.Usdviewq.stageView import StageView @@ -86,7 +88,9 @@ class USDViewer: def __init__(self, title: str = "Viewer", size: tuple[int, int] = (750, 750)): """Initialize the USD Viewer.""" - self._app = QtWidgets.QApplication([]) + # If app exists, use it. Otherwise, create a new one. + # Fixes issue of "QApplication instance already exists". + self._app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([]) self._title = title self._size = size @@ -129,7 +133,13 @@ def show(self) -> None: """Show the USD Viewer window. Displays the USD Viewer window and starts the Qt app event loop. + When :attr:`ansys.tools.usdviewer.OFF_SCREEN` or + :attr:`ansys.tools.usdviewer.BUILDING_GALLERY` is ``True``, this + method is a no-op so that documentation builds and automated tests + run without opening a display. """ + if _usdviewer.OFF_SCREEN or _usdviewer.BUILDING_GALLERY: + return self.window.show() self._app.exec() diff --git a/tests/conftest.py b/tests/conftest.py index 35fa081..4ed2fa4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,6 +28,8 @@ import pytest import pyvista +import ansys.tools.usdviewer as usdviewer + # Check if real pxr is available PXR_AVAILABLE = True try: @@ -107,5 +109,12 @@ def configure_pyvista(): return pyvista +@pytest.fixture(scope="session", autouse=True) +def configure_usdviewer(): + """Configure the USD viewer for testing.""" + usdviewer.OFF_SCREEN = True + return usdviewer + + # Mark for skipping tests that require real OpenUSD requires_openusd = pytest.mark.skipif(not PXR_AVAILABLE, reason="Test requires real OpenUSD library (not just mocks)")