diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f7354e9bc5..9e4a6c6c19 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -102,7 +102,7 @@ jobs: docs: name: Documentation if: github.event.action != 'closed' - runs-on: ubuntu-latest + runs-on: public-ubuntu-latest-16-cores needs: [docs-style] steps: - name: Login in Github Container registry @@ -126,6 +126,7 @@ jobs: needs-quarto: true sphinxopts: "-j auto --keep-going" env: + PYVISTA_BUILDING_GALLERY: 'True' PYPRIMEMESH_LAUNCH_CONTAINER: 1 PYPRIMEMESH_SPHINX_BUILD: 1 PYPRIMEMESH_IMAGE_TAG: ${{ env.DOCKER_IMAGE_TAG }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index beadc087f6..e17bb09cb3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,12 +40,6 @@ repos: - id: check-merge-conflict - id: debug-statements -# this validates our github workflow files -- repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.20.0 - hooks: - - id: check-github-workflows - # To be activated after quick dev cycles # - repo: https://github.com/pycqa/pydocstyle diff --git a/doc/changelog.d/1053.documentation.md b/doc/changelog.d/1053.documentation.md new file mode 100644 index 0000000000..af74b4f3ac --- /dev/null +++ b/doc/changelog.d/1053.documentation.md @@ -0,0 +1 @@ +Update ci_cd.yml \ No newline at end of file diff --git a/doc/changelog.d/1054.documentation.md b/doc/changelog.d/1054.documentation.md new file mode 100644 index 0000000000..6103dbf345 --- /dev/null +++ b/doc/changelog.d/1054.documentation.md @@ -0,0 +1 @@ +doc: parallel gallery \ No newline at end of file diff --git a/doc/changelog.d/1057.fixed.md b/doc/changelog.d/1057.fixed.md new file mode 100644 index 0000000000..5b2f0910e9 --- /dev/null +++ b/doc/changelog.d/1057.fixed.md @@ -0,0 +1 @@ +fix: unique container name \ No newline at end of file diff --git a/doc/changelog.d/1058.documentation.md b/doc/changelog.d/1058.documentation.md new file mode 100644 index 0000000000..74d30af0d5 --- /dev/null +++ b/doc/changelog.d/1058.documentation.md @@ -0,0 +1 @@ +Doc/parallel gallery \ No newline at end of file diff --git a/doc/changelog.d/1059.maintenance.md b/doc/changelog.d/1059.maintenance.md new file mode 100644 index 0000000000..b5ec1064bc --- /dev/null +++ b/doc/changelog.d/1059.maintenance.md @@ -0,0 +1 @@ +Feature: enable parallel execution of example scripts before sphinx build \ No newline at end of file diff --git a/doc/changelog.d/1073.miscellaneous.md b/doc/changelog.d/1073.miscellaneous.md new file mode 100644 index 0000000000..83cc27c6ce --- /dev/null +++ b/doc/changelog.d/1073.miscellaneous.md @@ -0,0 +1 @@ +Build(deps): bump ansys-tools-visualization-interface from 0.9.2 to 0.10.0 in the general-dependencies group \ No newline at end of file diff --git a/doc/changelog.d/1075.miscellaneous.md b/doc/changelog.d/1075.miscellaneous.md new file mode 100644 index 0000000000..5f4ac9a253 --- /dev/null +++ b/doc/changelog.d/1075.miscellaneous.md @@ -0,0 +1 @@ +Fix: wrong param in primeplotter \ No newline at end of file diff --git a/doc/changelog.d/1077.miscellaneous.md b/doc/changelog.d/1077.miscellaneous.md new file mode 100644 index 0000000000..3d97300d49 --- /dev/null +++ b/doc/changelog.d/1077.miscellaneous.md @@ -0,0 +1 @@ +Include ado's 25r2/sp01 changes \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index 0ef0e741be..e04cfe5b82 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,10 +1,17 @@ """Sphinx documentation configuration file.""" +import glob import os +import subprocess +import sys from datetime import datetime +# os.environ['PYVISTA_BUILDING_GALLERY'] = 'True' +os.environ["SPHINX_GALLERY_CONF_FORCE_FRESH"] = "0" + import ansys.tools.visualization_interface as viz_interface import pyvista from ansys_sphinx_theme import ansys_favicon, get_version_match, pyansys_logo_black +from joblib import Parallel, delayed from pyvista.plotting.utilities.sphinx_gallery import DynamicScraper from sphinx_gallery.sorting import FileNameSortKey @@ -161,9 +168,9 @@ # path where to save gallery generated examples "gallery_dirs": ["examples/gallery_examples"], # Pattern to search for example files - "filename_pattern": r"\.py", + "filename_pattern": r"^(?!examples/other/).*\.py$", # ignore mixing elbow and example template - "ignore_pattern": "examples/other_examples", + "ignore_pattern": r"examples/other/|flycheck*", # Remove the "Download all examples" button from the top level gallery "download_all_examples": False, # Sort gallery example by file name instead of number of lines (default) @@ -174,8 +181,62 @@ "doc_module": ("ansys.meshing.prime"), "exclude_implicit_doc": {"ansys\\.meshing\\.prime\\._.*"}, # ignore private submodules "image_scrapers": (DynamicScraper(), "matplotlib"), - "ignore_pattern": "flycheck*", "thumbnail_size": (350, 350), + "parallel": True, + "run_stale_examples": False, } + +def run_example(script_path): + """Run a Python script and return its exit code. + + Parameters + ---------- + script_path : str + The path to the Python script to execute. + + Returns + ------- + int + The exit code of the script execution. 0 indicates success. + """ + print(f"Running {script_path} ...") + result = subprocess.run([sys.executable, script_path], capture_output=True) + if result.returncode != 0: + print(f"Error in {script_path}:\n{result.stderr.decode()}") + return result.returncode + + +def run_all_examples_in_parallel(): + """Find and run all example Python scripts in parallel, excluding certain patterns. + + This function searches for all `.py` files under the `../../examples` directory, + excluding any scripts in 'examples/other' and any files containing 'flycheck' in their name. + All found scripts are executed in parallel using all available CPU cores. + """ + example_scripts = glob.glob( + os.path.join( + os.path.dirname(__file__), + "../../examples/**/*.py", + ), + recursive=True, + ) + # Exclude any scripts in 'examples/other' + example_scripts = [f for f in example_scripts if "examples/other" not in f.replace("\\", "/")] + # Exclude flycheck files if needed + example_scripts = [f for f in example_scripts if "flycheck" not in f] + Parallel(n_jobs=-1)(delayed(run_example)(script) for script in example_scripts) + + +def setup(app): + """Sphinx setup function to run all example scripts in parallel before building the docs. + + Parameters + ---------- + app : sphinx.application.Sphinx + The Sphinx application object. + """ + app.connect("builder-inited", lambda app: run_all_examples_in_parallel()) + + supress_warnings = ["docutils"] diff --git a/pyproject.toml b/pyproject.toml index 02b9dc5c62..92a0ab9696 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ graphics = [ "ansys-tools-visualization-interface>=0.4.7,<1", ] tests = [ - "ansys-tools-visualization-interface==0.9.2", + "ansys-tools-visualization-interface==0.11.0", "pytest==8.4.1", "pytest-cov==6.2.1", "pytest-pyvista==0.1.9", @@ -43,7 +43,8 @@ tests = [ ] doc = [ "ansys-sphinx-theme[autoapi]==1.5.2", - "ansys-tools-visualization-interface==0.9.2", + "ansys-tools-visualization-interface==0.11.0", + "joblib==1.5.1", "jupyter-sphinx==0.5.3", "numpydoc==1.8.0", "sphinx==8.2.3", diff --git a/src/ansys/meshing/prime/core/mapdlcdbexportutils.py b/src/ansys/meshing/prime/core/mapdlcdbexportutils.py index c67a7b5649..bc438ffb03 100644 --- a/src/ansys/meshing/prime/core/mapdlcdbexportutils.py +++ b/src/ansys/meshing/prime/core/mapdlcdbexportutils.py @@ -889,12 +889,14 @@ def _process_hyperfoam_data(self, property_dict, material, mat_id): hyperfoam_data = self._hyperfoam_with_test_data(n, uniaxial_test_data, poisson, mat_id) else: hyperfoam_data = self._hyperfoam_with_coeffs(n, data, mat_id) - self._logger.warning(f"{property_dict}") - self._logger.warning(f"{self._raw_materials_data[material]['UNIAXIAL TEST DATA']}") return hyperfoam_data def _hyperfoam_with_coeffs(self, n, data, mat_id): hyperfoam_coeff_data = '' + data = { + k: [float(x) for x in v if x is not None] if v is not None else None + for k, v in data.items() + } u1 = data['u1'] a1 = data['a1'] v1 = [0.0] * len(u1) @@ -957,7 +959,7 @@ def _hyperfoam_with_coeffs(self, n, data, mat_id): if n > 4: u5a = 2 * u5[i] / a5[i] a5a = a5[i] - hyperfoam_coeff_data += f", {u5a}, {a6a}" + hyperfoam_coeff_data += f", {u5a}, {a5a}" if n > 5: u6a = 2 * u6[i] / a6[i] a6a = a6[i] diff --git a/src/ansys/meshing/prime/graphics/plotter.py b/src/ansys/meshing/prime/graphics/plotter.py index f30cfd53f9..43bf7234bc 100644 --- a/src/ansys/meshing/prime/graphics/plotter.py +++ b/src/ansys/meshing/prime/graphics/plotter.py @@ -334,7 +334,7 @@ def show( if plottable_object is not None: self.plot(plottable_object, name_filter=name_filter, scope=scope, **plotting_options) self._backend.show( - object=plottable_object, + plottable_object=plottable_object, screenshot=screenshot, name_filter=name_filter, **plotting_options, diff --git a/src/ansys/meshing/prime/internals/launcher.py b/src/ansys/meshing/prime/internals/launcher.py index ef468c9120..514c716af8 100644 --- a/src/ansys/meshing/prime/internals/launcher.py +++ b/src/ansys/meshing/prime/internals/launcher.py @@ -264,7 +264,6 @@ def launch_prime( client = Client(port=port, timeout=timeout) client.container_name = container_name print('using server from docker : The container name ', container_name) - logging.getLogger('PyPrimeMesh').info('uses server from container : ', container_name) return client server = launch_server_process( diff --git a/src/ansys/meshing/prime/internals/utils.py b/src/ansys/meshing/prime/internals/utils.py index 6962e6d39d..5dbba30024 100644 --- a/src/ansys/meshing/prime/internals/utils.py +++ b/src/ansys/meshing/prime/internals/utils.py @@ -24,6 +24,7 @@ import os import shutil import subprocess +import uuid from contextlib import contextmanager from typing import List, Optional @@ -31,7 +32,6 @@ import ansys.meshing.prime.internals.defaults as defaults _LOCAL_PORTS = [] -_PRIME_CONTAINER_COUNT = 0 def make_unique_container_name(name: str): @@ -47,9 +47,7 @@ def make_unique_container_name(name: str): str Unique name with a numeric integer added as suffix. """ - global _PRIME_CONTAINER_COUNT - _PRIME_CONTAINER_COUNT = _PRIME_CONTAINER_COUNT + 1 - return f'{name}-{_PRIME_CONTAINER_COUNT}' + return f'{name}-' + str(uuid.uuid4()) def to_camel_case(snake_str):