From cb2659e49e31c0c0c4e62f27d872015b71d8a591 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 7 Jan 2026 14:30:51 -0600 Subject: [PATCH 01/14] update whatsnew and banner --- doc/changelog.d/whatsnew.yml | 204 +++++++++-------------------------- doc/source/conf.py | 5 + 2 files changed, 55 insertions(+), 154 deletions(-) diff --git a/doc/changelog.d/whatsnew.yml b/doc/changelog.d/whatsnew.yml index 3911cc9a71..f49eb299df 100644 --- a/doc/changelog.d/whatsnew.yml +++ b/doc/changelog.d/whatsnew.yml @@ -1,182 +1,78 @@ fragments: -- title: PEP 8 aliases for Mechanical APIs - version: 0.11.30 +- title: gRPC Security with mTLS, WNUA, and Insecure Transport Modes + version: 0.12.0 content: | - Mechanical APIs now support PEP 8 aliases for improved usability and consistency when used with PyMechanical. + PyMechanical now supports comprehensive gRPC security with three transport modes: mTLS (mutual TLS), + WNUA (Windows Named User Authentication), and insecure mode. Platform-aware defaults are automatically + selected (mTLS on Linux, WNUA on Windows) with automatic service pack detection and validation. - To enable PEP 8 aliases + **Transport Modes** + - ``mtls``: Mutual TLS authentication (Linux default) + - ``wnua``: Windows Named User Authentication (Windows default) + - ``insecure``: No authentication (required for older Mechanical versions) - .. code:: python - - from ansys.mechanical.core import App - - # Initialize the app and update globals - app = App(globals=globals(), pep8=True) - - Example on how to use the PEP 8 aliases are given below - - - .. code:: python - - from ansys.mechanical.core import App - - app = App(globals=globals(), pep8=True) - Model.add_static_structural_analysis() # Model.AddStaticStructuralAnalysis - Model.name = "Test" # Model.Name = "Test" - -- title: Globals parameter in the embedded app - version: 0.11.14 - content: | - The ``globals`` parameter of the `App `_ - class is used to update the global variables. This parameter is optional and interchangeable - with `app.update_globals(globals()) `_. - To exclude enums from the global variables, use ``app.update_globals(globals(), False)``. - See the `globals `_ page for more information. - - Using the ``globals`` parameter: - - .. code:: python - - from ansys.mechanical.core import App - - # Initialize the app and update globals - app = App(globals=globals()) - - Using the ``update_globals`` method: - - .. code:: python - - from ansys.mechanical.core import App + **New Parameters** - # Initialize the app and update globals - app = App() - app.update_globals(globals()) + All launch and connection APIs now support: - Using the ``update_globals`` method excluding enums from global variables: + - ``transport_mode``: Transport security mode (``"mtls"``, ``"wnua"``, or ``"insecure"``) + - ``certs_dir``: Certificate directory path for mTLS (default: ``"certs"``) + - ``grpc_options``: Custom gRPC channel options (e.g., ``[("grpc.default_authority", "localhost")]``) + - ``host``: Server binding address (default: ``"127.0.0.1"``, launch only) - .. code:: python + Affected APIs: ``launch_mechanical()``, ``connect_to_mechanical()``, ``launch_remote_mechanical()``, + ``Mechanical()``, ``LocalMechanicalPool()``, ``close_all_local_instances()`` - from ansys.mechanical.core import App + **Service Pack Requirements** - # Initialize the app and update globals - app = App() - app.update_globals(globals(), False) + Automatic detection validates Mechanical versions: -- title: Launch GUI - version: 0.11.8 - content: | - The `launch_gui() `_ function - graphically launches the current state of the embedded instance when the - `App `_ has been saved. + - 242 (2024 R2): Requires SP05 or later + - 251 (2025 R1): Requires SP04 or later + - 252 (2025 R2): Requires SP03 or later + - 261+ (2026 R1+): All service packs supported - The `launch_gui()` function saves the active `.mechdb` file and creates a copy of the existing - `.mechdb` file with a temporary name. The temporary `.mechdb` file is used to launch the GUI. - By default, the temporary `.mechdb` file is deleted after the GUI is closed, but the user can - specify whether or not to delete the temporary file. + **Usage Examples** - Usage: .. code:: python - from ansys.mechanical.core import App - - # Initialize and save the app - app = App() - app.save() - - # Launch the GUI and delete the temporary `.mechdb` file when the GUI is closed - app.launch_gui() - - # Launch the GUI and keep the temporary `.mechdb` file when the GUI is closed - app.launch_gui(delete_tmp_on_close=False) - -- title: Autocomplete settings command - version: 0.11.8 - content: | - The ``ansys-mechanical-ideconfig`` command prints the settings that are necessary for - autocomplete to work with ``ansys-mechanical-stubs``. This command takes in three arguments: - ``--ide vscode``, ``--target user`` or ``--target workspace``, and ``--revision ``. - If the revision is not provided, ``ansys-tools-path`` will retrieve the Mechanical version - from your system. - - Usage: - .. code:: shell - - ansys-mechanical-ideconfig --ide vscode --target user --revision 251 - - Terminal output for Windows user's settings.json file: - .. code:: shell + from ansys.mechanical.core import launch_mechanical - Update C:\Users\{username}\AppData\Roaming\Code\User\settings.json with the following information: + # Platform defaults (mTLS on Linux, WNUA on Windows) + mechanical = launch_mechanical() - { - "python.autoComplete.extraPaths": [ - "{project_directory}\\.venv\\Lib\\site-packages\\ansys\\mechanical\\stubs\\v251" - ], - "python.analysis.extraPaths": [ - "{project_directory}\\.venv\\Lib\\site-packages\\ansys\\mechanical\\stubs\\v251" - ] - } + # Explicit transport mode + mechanical = launch_mechanical(transport_mode="mtls", certs_dir="./certs") -- title: Visualize geometry in 3D - version: 0.11.4 - content: | - The `app.plot()` function allows you to visualize imported geometry in 3D. This feature is - available only from 24R1 or later and requires the `ansys-mechanical-core[graphics]` dependencies - to be installed: - - .. code:: shell - - pip install ansys-mechanical-core[graphics] - - Usage: - .. code:: python + # Custom gRPC options + mechanical = launch_mechanical( + transport_mode="mtls", + grpc_options=[("grpc.default_authority", "localhost")] + ) - from ansys.mechanical.core import App + # For older Mechanical versions (pre-SP04/SP05) + mechanical = launch_mechanical(transport_mode="insecure") - # Initialize the app and update globals - app = App() - app.update_globals(globals()) + **CLI Support** - # Import the geometry - app.open("path/to/file.mechdat") - - # Visualize - app.plot() - -- title: Print the Mechanical project tree - version: 0.11.1 - content: | - The `app.print_tree()` function prints the hierarchical tree representation of the - Mechanical project structure and object state. - - Usage: - .. code:: python + New command-line flags: - from ansys.mechanical.core import App + - ``--transport-mode {mtls,wnua,insecure}`` + - ``--certs-dir PATH`` + - ``--grpc-host HOST`` - # Initialize the app and update globals - app = App() - app.update_globals(globals()) + **Breaking Change** - # Print the entire tree - app.print_tree() + .. warning:: - # Print the entire tree but truncate the output after 2 lines - app.print_tree(max_lines=2) + Mechanical versions older than the required service packs (242 SP05, 251 SP04, 252 SP03) + will fail to launch with default settings. Explicitly set ``transport_mode="insecure"`` for + older versions: - # Print the tree for the Model and truncate after 3 lines - app.print_tree('Model', 3) + .. code:: python - Output for `app.print_tree()`: - .. code:: shell + # Required for old versions + mechanical = launch_mechanical(transport_mode="insecure") - ├── Project - | ├── Model - | | ├── Geometry Imports (⚡︎) - | | ├── Geometry (?) - | | ├── Materials (✓) - | | ├── Coordinate Systems (✓) - | | | ├── Global Coordinate System (✓) - | | ├── Remote Points (✓) - | | ├── Mesh (?) + See the `gRPC security documentation `_ for complete details on configuration. diff --git a/doc/source/conf.py b/doc/source/conf.py index 48585f2a85..5d990e18f3 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -215,6 +215,11 @@ "pyansys_tags": ["Structures"], } html_theme_options = { + "announcement": ( + "Starting with Pymechanical 0.12.0, Remote session uses secure server and connection. " + "Refer to this page for more information." + ), "logo": "pyansys", "switcher": { "json_url": f"https://{cname}/versions.json", From 2702fc0332861d1b1fe41d6576b838699fd3d57f Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Wed, 7 Jan 2026 20:32:19 +0000 Subject: [PATCH 02/14] chore: adding changelog file 1469.maintenance.md [dependabot-skip] --- doc/changelog.d/1469.maintenance.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/1469.maintenance.md diff --git a/doc/changelog.d/1469.maintenance.md b/doc/changelog.d/1469.maintenance.md new file mode 100644 index 0000000000..a51d4659a1 --- /dev/null +++ b/doc/changelog.d/1469.maintenance.md @@ -0,0 +1 @@ +Update whatsnew and banner From f0b3edbb87e6b5bbbdfaa437a116f7601ff30446 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 7 Jan 2026 15:59:53 -0600 Subject: [PATCH 03/14] fix doc build warning --- doc/changelog.d/whatsnew.yml | 79 ++++--------------- doc/source/conf.py | 7 +- doc/source/index.rst | 2 +- .../core/embedding/find_mechanical.py | 4 +- .../core/embedding/logger/__init__.py | 14 ++-- .../mechanical/core/embedding/transaction.py | 4 +- src/ansys/mechanical/core/ide_config.py | 4 +- src/ansys/mechanical/core/mechanical.py | 5 +- src/ansys/mechanical/core/run.py | 4 +- 9 files changed, 37 insertions(+), 86 deletions(-) diff --git a/doc/changelog.d/whatsnew.yml b/doc/changelog.d/whatsnew.yml index f49eb299df..d74293e834 100644 --- a/doc/changelog.d/whatsnew.yml +++ b/doc/changelog.d/whatsnew.yml @@ -2,77 +2,26 @@ fragments: - title: gRPC Security with mTLS, WNUA, and Insecure Transport Modes version: 0.12.0 content: | - PyMechanical now supports comprehensive gRPC security with three transport modes: mTLS (mutual TLS), - WNUA (Windows Named User Authentication), and insecure mode. Platform-aware defaults are automatically - selected (mTLS on Linux, WNUA on Windows) with automatic service pack detection and validation. + PyMechanical now supports comprehensive gRPC security with three transport modes: ``mtls`` (mutual TLS, + Linux default), ``wnua`` (Windows Named User Authentication, Windows default), and ``insecure`` mode. + Platform-aware defaults are automatically selected based on the operating system. - **Transport Modes** + The implementation includes automatic service pack detection and validation, custom gRPC channel options + support, and new CLI flags (``--transport-mode``, ``--certs-dir``, ``--grpc-host``). + All launch and connection APIs (``launch_mechanical()``, ``connect_to_mechanical()``, etc.) now support + ``transport_mode``, ``certs_dir``, ``grpc_options``, and ``host`` parameters for configuring gRPC security. - - ``mtls``: Mutual TLS authentication (Linux default) - - ``wnua``: Windows Named User Authentication (Windows default) - - ``insecure``: No authentication (required for older Mechanical versions) - - **New Parameters** - - All launch and connection APIs now support: - - - ``transport_mode``: Transport security mode (``"mtls"``, ``"wnua"``, or ``"insecure"``) - - ``certs_dir``: Certificate directory path for mTLS (default: ``"certs"``) - - ``grpc_options``: Custom gRPC channel options (e.g., ``[("grpc.default_authority", "localhost")]``) - - ``host``: Server binding address (default: ``"127.0.0.1"``, launch only) - - Affected APIs: ``launch_mechanical()``, ``connect_to_mechanical()``, ``launch_remote_mechanical()``, - ``Mechanical()``, ``LocalMechanicalPool()``, ``close_all_local_instances()`` - - **Service Pack Requirements** - - Automatic detection validates Mechanical versions: - - - 242 (2024 R2): Requires SP05 or later - - 251 (2025 R1): Requires SP04 or later - - 252 (2025 R2): Requires SP03 or later - - 261+ (2026 R1+): All service packs supported - - **Usage Examples** + Usage: .. code:: python - from ansys.mechanical.core import launch_mechanical - - # Platform defaults (mTLS on Linux, WNUA on Windows) - mechanical = launch_mechanical() - - # Explicit transport mode - mechanical = launch_mechanical(transport_mode="mtls", certs_dir="./certs") - - # Custom gRPC options - mechanical = launch_mechanical( - transport_mode="mtls", - grpc_options=[("grpc.default_authority", "localhost")] - ) - - # For older Mechanical versions (pre-SP04/SP05) - mechanical = launch_mechanical(transport_mode="insecure") - - **CLI Support** - - New command-line flags: - - - ``--transport-mode {mtls,wnua,insecure}`` - - ``--certs-dir PATH`` - - ``--grpc-host HOST`` - - **Breaking Change** - - .. warning:: + from ansys.mechanical.core import launch_mechanical - Mechanical versions older than the required service packs (242 SP05, 251 SP04, 252 SP03) - will fail to launch with default settings. Explicitly set ``transport_mode="insecure"`` for - older versions: + # Platform defaults (mTLS on Linux, WNUA on Windows) + mechanical = launch_mechanical() - .. code:: python + # For older versions without required service packs + mechanical = launch_mechanical(transport_mode="insecure") - # Required for old versions - mechanical = launch_mechanical(transport_mode="insecure") - See the `gRPC security documentation `_ for complete details on configuration. + For complete details, see the `gRPC Security User Guide `_. \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index 5d990e18f3..1a556041e2 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -115,6 +115,9 @@ numpydoc_validation_exclude = { # set of regex # grpc files r"\.*pb2\.*", + # Exclude built-in exception attributes from all exception classes + r".*__cause__$", + r".*__context__$", } # Favicon @@ -216,7 +219,7 @@ } html_theme_options = { "announcement": ( - "Starting with Pymechanical 0.12.0, Remote session uses secure server and connection. " + "Starting with Pymechanical 0.12.0, remote session uses secure server and connection. " "Refer to this page for more information." ), @@ -231,7 +234,7 @@ "show_breadcrumbs": True, "collapse_navigation": True, "use_edit_page_button": True, - "header_links_before_dropdown": 5, # number of links before the dropdown menu + "header_links_before_dropdown": 6, # number of links before the dropdown menu "additional_breadcrumbs": [ ("PyAnsys", "https://docs.pyansys.com/"), ], diff --git a/doc/source/index.rst b/doc/source/index.rst index c590a1d6f4..fe4e46c131 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -94,7 +94,7 @@ Python API to interact with `Ansys Mechanical`_ (FEA software for structural eng user_guide/index examples/index api/index - contribute faq + contribute kil/index changelog \ No newline at end of file diff --git a/src/ansys/mechanical/core/embedding/find_mechanical.py b/src/ansys/mechanical/core/embedding/find_mechanical.py index 28f41b349e..0a4b5e632a 100644 --- a/src/ansys/mechanical/core/embedding/find_mechanical.py +++ b/src/ansys/mechanical/core/embedding/find_mechanical.py @@ -60,8 +60,8 @@ def cli(version: int, path: str | None = None) -> tuple[int, str]: Optional path to the Ansys installation directory. eg: "usr/ansys_inc/v251/" - Example - ------- + Examples + -------- Get the version and location of the installation directory. >>> find-mechanical -r 251 diff --git a/src/ansys/mechanical/core/embedding/logger/__init__.py b/src/ansys/mechanical/core/embedding/logger/__init__.py index 4963fb7ba5..3a7c79e59d 100644 --- a/src/ansys/mechanical/core/embedding/logger/__init__.py +++ b/src/ansys/mechanical/core/embedding/logger/__init__.py @@ -24,9 +24,8 @@ Module to interact with the built-in logging system of Mechanical. -Usage ------ - +Examples +-------- Configuring logger ~~~~~~~~~~~~~~~~~~ @@ -34,11 +33,12 @@ :class:`Configuration ` class: .. code:: python - import ansys.mechanical.core as mech - from ansys.mechanical.core.embedding.logger import Configuration, Logger - Configuration.configure(level=logging.INFO, to_stdout=True, base_directory=None) - app = mech.App(version=252) + import ansys.mechanical.core as mech + from ansys.mechanical.core.embedding.logger import Configuration, Logger + + Configuration.configure(level=logging.INFO, to_stdout=True, base_directory=None) + app = mech.App(version=252) Then, the :class:`Logger ` class can be used to write messages to the log: diff --git a/src/ansys/mechanical/core/embedding/transaction.py b/src/ansys/mechanical/core/embedding/transaction.py index a855d39065..773d407d55 100644 --- a/src/ansys/mechanical/core/embedding/transaction.py +++ b/src/ansys/mechanical/core/embedding/transaction.py @@ -26,8 +26,8 @@ class Transaction: # When ansys-pythonnet issue #14 is fixed, this class will b """ A class to speed up bulk user interactions using Ansys ACT Mechanical Transaction. - Example - ------- + Examples + -------- >>> with Transaction() as transaction: ... pass # Perform bulk user interactions here """ diff --git a/src/ansys/mechanical/core/ide_config.py b/src/ansys/mechanical/core/ide_config.py index 31b5dc1b7e..e55ba7be29 100644 --- a/src/ansys/mechanical/core/ide_config.py +++ b/src/ansys/mechanical/core/ide_config.py @@ -207,8 +207,8 @@ def cli(ide: str, target: str, revision: int) -> None: The Mechanical revision number. For example, "252". If unspecified, it finds the default Mechanical version from ansys-tools-path. - Usage - ----- + Examples + -------- The following example demonstrates the main use of this tool: $ ansys-mechanical-ideconfig --ide vscode --target user --revision 252 diff --git a/src/ansys/mechanical/core/mechanical.py b/src/ansys/mechanical/core/mechanical.py index b6b8894bd2..e9ee4f431e 100644 --- a/src/ansys/mechanical/core/mechanical.py +++ b/src/ansys/mechanical/core/mechanical.py @@ -266,9 +266,8 @@ def get_mechanical_path(allow_input=True): def check_valid_mechanical(): """Change to see if the default Mechanical path is valid. - Example (windows) - ----------------- - + Examples + -------- >>> from ansys.mechanical.core import mechanical >>> from ansys.tools.common.path import change_default_mechanical_path >>> mechanical_path = "C:/Program Files/ANSYS Inc/v252/aisol/bin/win64/AnsysWBU.exe" diff --git a/src/ansys/mechanical/core/run.py b/src/ansys/mechanical/core/run.py index 6dea55ff53..d94ad1794b 100644 --- a/src/ansys/mechanical/core/run.py +++ b/src/ansys/mechanical/core/run.py @@ -463,8 +463,8 @@ def cli( ): """CLI tool to run mechanical. - USAGE: - + Examples + -------- The following example demonstrates the main use of this tool: $ ansys-mechanical -r 252 -g From 6556d385fef603bbc2e2281a0f0a8fd4f16d33a2 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 7 Jan 2026 16:12:13 -0600 Subject: [PATCH 04/14] add autocomplete in toctree --- doc/source/user_guide/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/user_guide/index.rst b/doc/source/user_guide/index.rst index 1c025be31c..c1c24a6e60 100644 --- a/doc/source/user_guide/index.rst +++ b/doc/source/user_guide/index.rst @@ -32,6 +32,7 @@ detailed how-to guides on specific topics. The user guide is divided into the fo howto/libraries howto/logging howto/pep8 + howto/autocomplete .. toctree:: :maxdepth: 1 From 2a99962b30fe2395a3259ee6cb05057e34590c02 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 8 Jan 2026 10:01:39 -0600 Subject: [PATCH 05/14] re add old fragments --- doc/changelog.d/whatsnew.yml | 184 +++++++++++++++++- doc/source/conf.py | 5 - .../remote_session/grpc_security.rst | 6 + 3 files changed, 189 insertions(+), 6 deletions(-) diff --git a/doc/changelog.d/whatsnew.yml b/doc/changelog.d/whatsnew.yml index d74293e834..d6aeecb5ab 100644 --- a/doc/changelog.d/whatsnew.yml +++ b/doc/changelog.d/whatsnew.yml @@ -24,4 +24,186 @@ fragments: mechanical = launch_mechanical(transport_mode="insecure") - For complete details, see the `gRPC Security User Guide `_. \ No newline at end of file + For complete details, see the `gRPC Security User Guide `_. + +- title: PEP 8 aliases for Mechanical APIs + version: 0.11.30 + content: | + Mechanical APIs now support PEP 8 aliases for improved usability and consistency when used with PyMechanical. + + To enable PEP 8 aliases + + + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App(globals=globals(), pep8=True) + + Example on how to use the PEP 8 aliases are given below + + + .. code:: python + + from ansys.mechanical.core import App + + app = App(globals=globals(), pep8=True) + Model.add_static_structural_analysis() # Model.AddStaticStructuralAnalysis + Model.name = "Test" # Model.Name = "Test" + +- title: Globals parameter in the embedded app + version: 0.11.14 + content: | + The ``globals`` parameter of the `App `_ + class is used to update the global variables. This parameter is optional and interchangeable + with `app.update_globals(globals()) `_. + To exclude enums from the global variables, use ``app.update_globals(globals(), False)``. + See the `globals `_ page for more information. + + Using the ``globals`` parameter: + + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App(globals=globals()) + + Using the ``update_globals`` method: + + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App() + app.update_globals(globals()) + + Using the ``update_globals`` method excluding enums from global variables: + + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App() + app.update_globals(globals(), False) + +- title: Launch GUI + version: 0.11.8 + content: | + The `launch_gui() `_ function + graphically launches the current state of the embedded instance when the + `App `_ has been saved. + + The `launch_gui()` function saves the active `.mechdb` file and creates a copy of the existing + `.mechdb` file with a temporary name. The temporary `.mechdb` file is used to launch the GUI. + By default, the temporary `.mechdb` file is deleted after the GUI is closed, but the user can + specify whether or not to delete the temporary file. + + Usage: + .. code:: python + + from ansys.mechanical.core import App + + # Initialize and save the app + app = App() + app.save() + + # Launch the GUI and delete the temporary `.mechdb` file when the GUI is closed + app.launch_gui() + + # Launch the GUI and keep the temporary `.mechdb` file when the GUI is closed + app.launch_gui(delete_tmp_on_close=False) + +- title: Autocomplete settings command + version: 0.11.8 + content: | + The ``ansys-mechanical-ideconfig`` command prints the settings that are necessary for + autocomplete to work with ``ansys-mechanical-stubs``. This command takes in three arguments: + ``--ide vscode``, ``--target user`` or ``--target workspace``, and ``--revision ``. + If the revision is not provided, ``ansys-tools-path`` will retrieve the Mechanical version + from your system. + + Usage: + .. code:: shell + + ansys-mechanical-ideconfig --ide vscode --target user --revision 251 + + Terminal output for Windows user's settings.json file: + .. code:: shell + + Update C:\Users\{username}\AppData\Roaming\Code\User\settings.json with the following information: + + { + "python.autoComplete.extraPaths": [ + "{project_directory}\\.venv\\Lib\\site-packages\\ansys\\mechanical\\stubs\\v251" + ], + "python.analysis.extraPaths": [ + "{project_directory}\\.venv\\Lib\\site-packages\\ansys\\mechanical\\stubs\\v251" + ] + } + +- title: Visualize geometry in 3D + version: 0.11.4 + content: | + The `app.plot()` function allows you to visualize imported geometry in 3D. This feature is + available only from 24R1 or later and requires the `ansys-mechanical-core[graphics]` dependencies + to be installed: + + .. code:: shell + + pip install ansys-mechanical-core[graphics] + + Usage: + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App() + app.update_globals(globals()) + + # Import the geometry + app.open("path/to/file.mechdat") + + # Visualize + app.plot() + +- title: Print the Mechanical project tree + version: 0.11.1 + content: | + The `app.print_tree()` function prints the hierarchical tree representation of the + Mechanical project structure and object state. + + Usage: + .. code:: python + + from ansys.mechanical.core import App + + # Initialize the app and update globals + app = App() + app.update_globals(globals()) + + # Print the entire tree + app.print_tree() + + # Print the entire tree but truncate the output after 2 lines + app.print_tree(max_lines=2) + + # Print the tree for the Model and truncate after 3 lines + app.print_tree('Model', 3) + + Output for `app.print_tree()`: + .. code:: shell + + ├── Project + | ├── Model + | | ├── Geometry Imports (⚡︎) + | | ├── Geometry (?) + | | ├── Materials (✓) + | | ├── Coordinate Systems (✓) + | | | ├── Global Coordinate System (✓) + | | ├── Remote Points (✓) + | | ├── Mesh (?) diff --git a/doc/source/conf.py b/doc/source/conf.py index 1a556041e2..93dd90fd6b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -218,11 +218,6 @@ "pyansys_tags": ["Structures"], } html_theme_options = { - "announcement": ( - "Starting with Pymechanical 0.12.0, remote session uses secure server and connection. " - "Refer to this page for more information." - ), "logo": "pyansys", "switcher": { "json_url": f"https://{cname}/versions.json", diff --git a/doc/source/user_guide/remote_session/grpc_security.rst b/doc/source/user_guide/remote_session/grpc_security.rst index 09a97e2e38..9bf5b5685c 100644 --- a/doc/source/user_guide/remote_session/grpc_security.rst +++ b/doc/source/user_guide/remote_session/grpc_security.rst @@ -139,8 +139,14 @@ CLI usage # Insecure mode ansys-mechanical --port 10000 --transport-mode insecure + # Specify custom host for gRPC binding + ansys-mechanical --port 10000 --transport-mode wnua --grpc-host 127.0.0.1 + If ``--transport-mode`` is not specified, the platform default is used. +The ``--grpc-host`` option specifies the host address for the gRPC server to bind to. +It defaults to ``localhost`` for WNUA and insecure modes. + Connect to an existing instance ------------------------------- From a2fc9013f6ef628316d1b1d926cae66426ac411c Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 8 Jan 2026 10:16:18 -0600 Subject: [PATCH 06/14] review suggestions --- .../remote_session/grpc_security.rst | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/doc/source/user_guide/remote_session/grpc_security.rst b/doc/source/user_guide/remote_session/grpc_security.rst index 9bf5b5685c..6acdce723c 100644 --- a/doc/source/user_guide/remote_session/grpc_security.rst +++ b/doc/source/user_guide/remote_session/grpc_security.rst @@ -3,11 +3,15 @@ Secure gRPC connections ======================= -PyMechanical supports secure gRPC connections using mTLS, WNUA, or insecure modes. +PyMechanical supports gRPC connections using mTLS, WNUA, or insecure modes. -.. warning:: - Secure connections (mTLS, WNUA) require specific service packs for each version. - Versions without the required service pack only support insecure mode. +**Transport mode comparison:** + +- **mTLS**: Provides both authentication and encryption. Recommended for production environments. +- **WNUA** (Windows only): Provides authentication but not encryption. +- **Insecure**: No authentication or encryption. Not recommended. + +See the table below for version-specific support and service pack requirements. Version and service pack requirements ------------------------------------- @@ -49,25 +53,37 @@ Version and service pack requirements Ansys installation directory. .. warning:: - **Breaking Change**: Version mismatch behavior + **Breaking Change**: Version mismatch behavior on Linux + + **Windows users**: No breaking changes. The default WNUA mode works across all versions + and does not require certificates or additional configuration. + + **Linux users**: Breaking change introduced due to mTLS default requiring certificates. - When using ``launch_mechanical()`` without explicitly specifying ``transport_mode``: + When using ``launch_mechanical()`` on Linux without explicitly specifying ``transport_mode``: - - If you have a **newer version of PyMechanical** with an **older version of Mechanical** - that doesn't support secure connections, the connection will fail. - - If you have an **older version of PyMechanical** with a **newer version of Mechanical** - that requires secure connections by default, the connection will fail. + - If you have a **newer version of PyMechanical** (0.12.0+) with an **older version of Mechanical** + (without required service pack), the connection will fail because PyMechanical defaults to mTLS + but the old Mechanical version doesn't support it. + - If you have an **older version of PyMechanical** (< 0.12.0) with a **newer version of Mechanical** + (with required service pack), the connection may fail due to security mode mismatch. - **Solution**: Always explicitly specify ``transport_mode`` to avoid compatibility issues: + **Solution for Linux users**: Always explicitly specify ``transport_mode``: .. code-block:: python - # For older Mechanical versions (241 or versions without required SP) + # For older Mechanical versions on Linux (241 or versions without required SP) mechanical = launch_mechanical(transport_mode="insecure") - # For newer Mechanical versions with secure support - mechanical = launch_mechanical(transport_mode="wnua") # Windows - mechanical = launch_mechanical(transport_mode="mtls") # Linux + # For newer Mechanical versions on Linux with certificates configured + mechanical = launch_mechanical(transport_mode="mtls", certs_dir="/path/to/certs") + + **Windows users** can continue using the default without changes: + + .. code-block:: python + + # Works on all Windows versions (WNUA default) + mechanical = launch_mechanical() Transport modes --------------- @@ -113,7 +129,7 @@ See `PyAnsys mTLS guide Date: Fri, 9 Jan 2026 15:31:25 +0000 Subject: [PATCH 07/14] chore: adding changelog file 1469.maintenance.md [dependabot-skip] --- doc/changelog.d/1469.maintenance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.d/1469.maintenance.md b/doc/changelog.d/1469.maintenance.md index a51d4659a1..bff54a16bf 100644 --- a/doc/changelog.d/1469.maintenance.md +++ b/doc/changelog.d/1469.maintenance.md @@ -1 +1 @@ -Update whatsnew and banner +Update whatsnew and doc From bbb41fdbaf7879c1ac1aaf81387f5bca4611211b Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 12 Jan 2026 10:30:02 -0600 Subject: [PATCH 08/14] add warning instead of breaking workflow --- .../remote_session/grpc_security.rst | 50 +++++++------------ src/ansys/mechanical/core/__init__.py | 2 +- src/ansys/mechanical/core/launcher.py | 7 +-- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/doc/source/user_guide/remote_session/grpc_security.rst b/doc/source/user_guide/remote_session/grpc_security.rst index 6acdce723c..d6f6026d06 100644 --- a/doc/source/user_guide/remote_session/grpc_security.rst +++ b/doc/source/user_guide/remote_session/grpc_security.rst @@ -52,38 +52,28 @@ Version and service pack requirements - To check your service pack version, look at the ``builddate.txt`` file in your Ansys installation directory. -.. warning:: - **Breaking Change**: Version mismatch behavior on Linux - - **Windows users**: No breaking changes. The default WNUA mode works across all versions - and does not require certificates or additional configuration. - - **Linux users**: Breaking change introduced due to mTLS default requiring certificates. +.. note:: + **Backward Compatibility**: Version mismatch behavior - When using ``launch_mechanical()`` on Linux without explicitly specifying ``transport_mode``: + When using ``launch_mechanical()`` without explicitly specifying ``transport_mode``: - - If you have a **newer version of PyMechanical** (0.12.0+) with an **older version of Mechanical** - (without required service pack), the connection will fail because PyMechanical defaults to mTLS - but the old Mechanical version doesn't support it. - - If you have an **older version of PyMechanical** (< 0.12.0) with a **newer version of Mechanical** - (with required service pack), the connection may fail due to security mode mismatch. + - If you have a **newer version of PyMechanical** with an **older version of Mechanical** + that doesn't support secure connections, PyMechanical automatically falls back to + **insecure mode** with a warning. The connection succeeds. + - If you have an **older version of PyMechanical** with a **newer version of Mechanical** + that requires secure connections by default, you may need to update PyMechanical. - **Solution for Linux users**: Always explicitly specify ``transport_mode``: + **Best Practice**: Explicitly specify ``transport_mode`` to avoid warnings and ensure + predictable behavior: .. code-block:: python - # For older Mechanical versions on Linux (241 or versions without required SP) + # For older Mechanical versions (241 or versions without required SP) mechanical = launch_mechanical(transport_mode="insecure") - # For newer Mechanical versions on Linux with certificates configured - mechanical = launch_mechanical(transport_mode="mtls", certs_dir="/path/to/certs") - - **Windows users** can continue using the default without changes: - - .. code-block:: python - - # Works on all Windows versions (WNUA default) - mechanical = launch_mechanical() + # For newer Mechanical versions with secure support + mechanical = launch_mechanical(transport_mode="wnua") # Windows + mechanical = launch_mechanical(transport_mode="mtls") # Linux Transport modes --------------- @@ -114,8 +104,8 @@ See `PyAnsys mTLS guide Date: Mon, 12 Jan 2026 10:54:38 -0600 Subject: [PATCH 09/14] inhibit launch if no server cert found --- src/ansys/mechanical/core/launcher.py | 5 +++++ src/ansys/mechanical/core/misc.py | 28 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/ansys/mechanical/core/launcher.py b/src/ansys/mechanical/core/launcher.py index 3c31822e7a..71e6ca3d01 100644 --- a/src/ansys/mechanical/core/launcher.py +++ b/src/ansys/mechanical/core/launcher.py @@ -33,6 +33,7 @@ from ansys.mechanical.core import LOG from ansys.mechanical.core.misc import ( + check_sever_certs_exist, get_service_pack_message, has_grpc_service_pack, is_linux, @@ -101,8 +102,12 @@ def __init__( else: transport_mode = "wnua" self.transport_mode = transport_mode + # Resolve certs_dir using environment variable if needed for mTLS self.certs_dir = resolve_certs_dir(transport_mode, certs_dir) + if transport_mode.lower() == "mtls": + # Check that certs exist if needed for mTLS + check_sever_certs_exist(self.certs_dir) self.__ui_arg_list = ["-DSApplet", "-nosplash", "-notabctrl"] self.__batch_arg_list = ["-DSApplet", "-b"] diff --git a/src/ansys/mechanical/core/misc.py b/src/ansys/mechanical/core/misc.py index b967937c24..1e4f54e336 100644 --- a/src/ansys/mechanical/core/misc.py +++ b/src/ansys/mechanical/core/misc.py @@ -355,3 +355,31 @@ def resolve_certs_dir(transport_mode, certs_dir=None): # On Linux, read at any level return os.environ.get("ANSYS_GRPC_CERTIFICATES", "certs") return certs_dir if certs_dir is not None else "certs" + + +def check_sever_certs_exist(certs_dir: str) -> None: + """Check if the required certificate files exist in the specified directory. + + Parameters + ---------- + certs_dir : str + Directory path where the certificate files are expected. + + Raises + ------ + FileNotFoundError + If any of the required certificate files are missing. + """ + required_files_server = ["server.cert", "server.key", "ca.cert"] + missing_files = [] + for filename in required_files_server: + file_path = Path(certs_dir) / filename + if not file_path.is_file(): + missing_files.append(filename) + + if missing_files: + missing_str = ", ".join(missing_files) + raise FileNotFoundError( + f"Could not launch Ansys Mechanical in mtls transport mode. " + f"The following certificate files are missing in '{certs_dir}': {missing_str}" + ) From e1623f683e1e7586de2d7ac33cef73d697e37c6a Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 12 Jan 2026 10:58:08 -0600 Subject: [PATCH 10/14] re org func --- src/ansys/mechanical/core/misc.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ansys/mechanical/core/misc.py b/src/ansys/mechanical/core/misc.py index 1e4f54e336..96cffcc56f 100644 --- a/src/ansys/mechanical/core/misc.py +++ b/src/ansys/mechanical/core/misc.py @@ -42,6 +42,16 @@ def is_windows(): return False +def is_linux() -> bool: + """Check if the host machine is Linux. + + Returns + ------- + ``True`` if the host machine is Linux, ``False`` otherwise. + """ + return os.name == "posix" + + def get_mechanical_bin(release_version): """Get the path for the Mechanical executable file based on the release version. @@ -303,16 +313,6 @@ def get_service_pack_message(version): return "Update to Ansys 2024 R2 or later for secure gRPC support." -def is_linux() -> bool: - """Check if the host machine is Linux. - - Returns - ------- - ``True`` if the host machine is Linux, ``False`` otherwise. - """ - return os.name == "posix" - - def resolve_certs_dir(transport_mode, certs_dir=None): """Resolve the certificate directory for mTLS connections. From 33ba5df756d4e5746fb207bf603915e5169cbfef Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 12 Jan 2026 11:06:28 -0600 Subject: [PATCH 11/14] update func name --- src/ansys/mechanical/core/launcher.py | 4 ++-- src/ansys/mechanical/core/misc.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ansys/mechanical/core/launcher.py b/src/ansys/mechanical/core/launcher.py index 71e6ca3d01..d2070bc3d4 100644 --- a/src/ansys/mechanical/core/launcher.py +++ b/src/ansys/mechanical/core/launcher.py @@ -33,11 +33,11 @@ from ansys.mechanical.core import LOG from ansys.mechanical.core.misc import ( - check_sever_certs_exist, get_service_pack_message, has_grpc_service_pack, is_linux, resolve_certs_dir, + verify_server_certificates, ) @@ -107,7 +107,7 @@ def __init__( self.certs_dir = resolve_certs_dir(transport_mode, certs_dir) if transport_mode.lower() == "mtls": # Check that certs exist if needed for mTLS - check_sever_certs_exist(self.certs_dir) + verify_server_certificates(self.certs_dir) self.__ui_arg_list = ["-DSApplet", "-nosplash", "-notabctrl"] self.__batch_arg_list = ["-DSApplet", "-b"] diff --git a/src/ansys/mechanical/core/misc.py b/src/ansys/mechanical/core/misc.py index 96cffcc56f..743afc2b3b 100644 --- a/src/ansys/mechanical/core/misc.py +++ b/src/ansys/mechanical/core/misc.py @@ -357,8 +357,8 @@ def resolve_certs_dir(transport_mode, certs_dir=None): return certs_dir if certs_dir is not None else "certs" -def check_sever_certs_exist(certs_dir: str) -> None: - """Check if the required certificate files exist in the specified directory. +def verify_server_certificates(certs_dir: str) -> None: + """Check if the required server certificate files exist in the specified directory. Parameters ---------- From 7a1619954de7a07b1cbe9eabe23ffba0423ca3b2 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 12 Jan 2026 13:57:34 -0600 Subject: [PATCH 12/14] update breaking change in doc --- .../remote_session/grpc_security.rst | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/doc/source/user_guide/remote_session/grpc_security.rst b/doc/source/user_guide/remote_session/grpc_security.rst index d6f6026d06..69802dd3d1 100644 --- a/doc/source/user_guide/remote_session/grpc_security.rst +++ b/doc/source/user_guide/remote_session/grpc_security.rst @@ -52,28 +52,34 @@ Version and service pack requirements - To check your service pack version, look at the ``builddate.txt`` file in your Ansys installation directory. -.. note:: - **Backward Compatibility**: Version mismatch behavior +.. warning:: + **Breaking Change for Linux Users** + + If you have the **latest PyMechanical** with an **older version of Mechanical** + that doesn't support secure connections (pre-2024 R2 or without required service pack): - When using ``launch_mechanical()`` without explicitly specifying ``transport_mode``: + - **Linux**: The default transport mode is ``mtls``. Calling ``launch_mechanical()`` + without explicitly specifying ``transport_mode="insecure"`` **will fail** because + old Mechanical versions don't support mtls. - - If you have a **newer version of PyMechanical** with an **older version of Mechanical** - that doesn't support secure connections, PyMechanical automatically falls back to - **insecure mode** with a warning. The connection succeeds. - - If you have an **older version of PyMechanical** with a **newer version of Mechanical** - that requires secure connections by default, you may need to update PyMechanical. + - **Windows**: The default transport mode is ``wnua``. A warning is issued and the + connection **automatically falls back to insecure mode**. The connection succeeds, + but you should explicitly specify ``transport_mode="insecure"`` to avoid the warning. - **Best Practice**: Explicitly specify ``transport_mode`` to avoid warnings and ensure - predictable behavior: + **Required Action for Linux**: Always explicitly specify ``transport_mode="insecure"`` + when using old Mechanical versions: .. code-block:: python - # For older Mechanical versions (241 or versions without required SP) + # Required for Mechanical 241 or versions without required SP mechanical = launch_mechanical(transport_mode="insecure") - # For newer Mechanical versions with secure support - mechanical = launch_mechanical(transport_mode="wnua") # Windows - mechanical = launch_mechanical(transport_mode="mtls") # Linux +.. note:: + **Forward Compatibility** + + If you have an **older version of PyMechanical** with a **newer version of Mechanical** + that supports secure connections by default, you may need to update PyMechanical to + take advantage of secure transport modes. Transport modes --------------- From 851ee01ddb76aee2b11426da17f1d5129eef378b Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Wed, 18 Feb 2026 19:24:25 +0000 Subject: [PATCH 13/14] chore: adding changelog file 1469.maintenance.md [dependabot-skip] --- doc/changelog.d/1469.maintenance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.d/1469.maintenance.md b/doc/changelog.d/1469.maintenance.md index bff54a16bf..53fb594a06 100644 --- a/doc/changelog.d/1469.maintenance.md +++ b/doc/changelog.d/1469.maintenance.md @@ -1 +1 @@ -Update whatsnew and doc +Update gPRC documentation From f766fc918e33c983795cec69a55fe4465571e87d Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 11 Mar 2026 20:05:17 -0500 Subject: [PATCH 14/14] update doc --- .../remote_session/grpc_security.rst | 108 +++++++++++++++++- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/doc/source/user_guide/remote_session/grpc_security.rst b/doc/source/user_guide/remote_session/grpc_security.rst index 69802dd3d1..f850888c31 100644 --- a/doc/source/user_guide/remote_session/grpc_security.rst +++ b/doc/source/user_guide/remote_session/grpc_security.rst @@ -5,11 +5,111 @@ Secure gRPC connections PyMechanical supports gRPC connections using mTLS, WNUA, or insecure modes. -**Transport mode comparison:** +.. _transport_modes: -- **mTLS**: Provides both authentication and encryption. Recommended for production environments. -- **WNUA** (Windows only): Provides authentication but not encryption. -- **Insecure**: No authentication or encryption. Not recommended. +Transport mode comparison +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. _mtls_mode: + +**mTLS (Mutual TLS)** + +Provides certificate-based mutual authentication and encryption. Both server and client must possess valid certificates signed by the same Certificate Authority (CA). This mode is platform-independent and recommended for production deployments requiring strong security. + +*Authentication mechanism:* Both parties validate each other's certificates against a trusted CA. The connection is rejected if either certificate is invalid or untrusted. + +*Encryption:* All data transmitted is encrypted using TLS protocol. + +*Cross-platform:* Works on Windows and Linux. + +*Network scope:* Can operate across any network including the internet, cloud deployments, and remote connections. + +.. _wnua_mode: + +**WNUA (Windows Named User Authentication)** + +Windows-only mode that authenticates using the current Windows user's credentials through SSPI/Negotiate protocol. Provides authentication based on Windows identity but does not encrypt the data channel. + +*Authentication mechanism:* The client authenticates as the currently logged-in Windows user. Only the same Windows user account can connect to the server, regardless of which machine they're connecting from within the domain/workgroup. + +*Encryption:* Authentication is secure, but the data channel is **not encrypted**. + +*Platform restriction:* Windows only. Both server and client must be Windows systems. + +*Network scope:* Limited to Windows domain/workgroup networks. Does not work across domain boundaries without proper trust relationships. + +*Access control:* Only the same Windows user who started the server can connect, even from different machines. + +.. _insecure_mode: + +**Insecure** + +Provides no authentication or encryption. Any client that can reach the network port can connect without credentials. + +*Authentication mechanism:* None. Any client can connect. + +*Encryption:* None. All data is transmitted in plaintext. + +*Security risk:* Suitable only for local development on trusted machines. Never use in production or on untrusted networks. + +.. _host_and_ip: + +Host binding +^^^^^^^^^^^^ + +The server's host address determines which network interfaces accept connections: + +- **127.0.0.1 (localhost)**: Listens only on loopback. Only same-machine clients can connect. Traffic never leaves the machine. + +- **0.0.0.0 (all interfaces)**: Listens on all network interfaces. Any client that can route to the machine can attempt connection, subject to transport mode authentication. + +- **Specific IP** (e.g., 192.168.1.100): Listens only on that interface. Only clients that can route to that specific IP can attempt connection. + +.. _ip_connectivity: + +Client connectivity by IP and transport mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Server on 0.0.0.0 (all interfaces):** + +- **mTLS**: Any client from any network with valid certificates can connect. Access controlled by certificate validation. +- **WNUA**: Only same Windows user can connect, from same or different machines within domain/workgroup. Different users blocked. +- **Insecure**: Anyone who can reach the port can connect. No restrictions. High security risk. + +**Server on 127.0.0.1 (localhost only):** + +- **mTLS**: Only local clients with valid certificates can connect. +- **WNUA**: Only same Windows user on same machine can connect. +- **Insecure**: Only local clients can connect. Relatively safe for development. + +**Server on specific IP:** + +- **mTLS**: Clients that can route to that IP with valid certificates can connect. +- **WNUA**: Same Windows user from machines that can route to that IP can connect. +- **Insecure**: Anyone who can route to that IP can connect. Security risk on shared networks. + +**Summary table:** + +.. list-table:: + :header-rows: 1 + :widths: 20 30 25 25 + + * - Transport Mode + - Authentication + - Encryption + - Connectivity Scope + * - mTLS + - Certificate-based + - Yes (TLS) + - Any network with valid certs + * - WNUA + - Windows user identity + - No + - Same Windows user only + * - Insecure + - None + - No + - Unrestricted (dangerous) See the table below for version-specific support and service pack requirements.