├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── ci-build.yml │ ├── create-milestone.yml │ └── update-gh-pages.yml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.rst ├── doc ├── .vale.ini ├── Makefile ├── make.bat ├── source │ ├── _static │ │ ├── css │ │ │ └── landing_page.css │ │ ├── icons │ │ │ ├── ai-ml.svg │ │ │ ├── ansys-icon-dark.svg │ │ │ ├── ansys-icon-light.svg │ │ │ ├── connect.svg │ │ │ ├── design.svg │ │ │ ├── digital-twins.svg │ │ │ ├── electromagnetics.svg │ │ │ ├── embedded-software.svg │ │ │ ├── fluids.svg │ │ │ ├── materials.svg │ │ │ ├── optics.svg │ │ │ ├── platform.svg │ │ │ ├── semiconductors.svg │ │ │ ├── sound.svg │ │ │ └── structures.svg │ │ ├── js │ │ │ └── landing_page.js │ │ ├── pyansys_dark.png │ │ └── thumbnails │ │ │ ├── 5gwizard.png │ │ │ ├── ansys-python-manager.png │ │ │ ├── intro.png │ │ │ ├── pyacp.png │ │ │ ├── pyaedt.png │ │ │ ├── pyansys-cheat-sheets.png │ │ │ ├── pyansys-common.png │ │ │ ├── pyansys-geometry.png │ │ │ ├── pyansys-math.png │ │ │ ├── pyansys-sound.png │ │ │ ├── pyconceptev.png │ │ │ ├── pydpf-composites.png │ │ │ ├── pydpf-core.png │ │ │ ├── pydpf-post.png │ │ │ ├── pydyna.png │ │ │ ├── pydynamicreporting.png │ │ │ ├── pyedb.png │ │ │ ├── pyensight.png │ │ │ ├── pyfluent-parametric.png │ │ │ ├── pyfluent-visualization.png │ │ │ ├── pyfluent.png │ │ │ ├── pygranta.png │ │ │ ├── pymapdl.png │ │ │ ├── pymapdl_dark.png │ │ │ ├── pymapdl_reader.png │ │ │ ├── pymechanical.png │ │ │ ├── pymodelcenter.png │ │ │ ├── pymotorcad.png │ │ │ ├── pyoptislang.png │ │ │ ├── pyprimemesh.png │ │ │ ├── pyrocky.png │ │ │ ├── pyscadeone.png │ │ │ ├── pysherlock.png │ │ │ ├── pysimai.png │ │ │ ├── pyspeos.png │ │ │ ├── pysystem-coupling.png │ │ │ ├── pyturbogrid.png │ │ │ └── pytwin.png │ ├── _templates │ │ └── landing_page_sidebar.html │ ├── api.rst │ ├── conf.py │ ├── examples.rst │ ├── getting-started.rst │ ├── getting-started │ │ ├── about.rst │ │ ├── install.rst │ │ └── prerequisites.rst │ ├── index.rst │ ├── links.rst │ ├── tools │ │ ├── index.rst │ │ ├── libraries │ │ │ └── index.rst │ │ ├── standalone │ │ │ └── index.rst │ │ └── toolkits │ │ │ └── index.rst │ └── user_guide.rst └── styles │ ├── .gitignore │ └── config │ └── vocabularies │ └── ANSYS │ ├── accept.txt │ └── reject.txt ├── ignore_words.txt ├── projects.yaml ├── pyproject.toml ├── src └── pyansys │ └── __init__.py └── tools ├── catsitemap.py ├── links.py └── milestone.py /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pip" 4 | directory: "/" 5 | insecure-external-code-execution: allow 6 | schedule: 7 | interval: "daily" 8 | groups: 9 | deps: 10 | patterns: 11 | - "*" 12 | 13 | - package-ecosystem: "github-actions" 14 | directory: "/" 15 | schedule: 16 | interval: "daily" 17 | groups: 18 | actions: 19 | patterns: 20 | - "*" 21 | -------------------------------------------------------------------------------- /.github/workflows/ci-build.yml: -------------------------------------------------------------------------------- 1 | name: GitHub CI 2 | on: 3 | pull_request: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "*" 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | env: 16 | PACKAGE_NAME: pyansys 17 | PACKAGE_NAMESPACE: pyansys 18 | MAIN_PYTHON_VERSION: '3.11' 19 | DOCUMENTATION_CNAME: "docs.pyansys.com" 20 | 21 | jobs: 22 | check-vulnerabilities: 23 | name: Check third-party dependencies for vulnerabilities 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: PyAnsys Vulnerability Check (on PRs) 27 | if: github.event_name == 'pull_request' 28 | uses: ansys/actions/check-vulnerabilities@v10 29 | with: 30 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 31 | python-package-name: ${{ env.PACKAGE_NAME }} 32 | token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} 33 | dev-mode: true 34 | 35 | - name: PyAnsys Vulnerability Check (any other case) 36 | if: github.event_name != 'pull_request' 37 | uses: ansys/actions/check-vulnerabilities@v10 38 | with: 39 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 40 | python-package-name: ${{ env.PACKAGE_NAME }} 41 | token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} 42 | 43 | check-licenses: 44 | name: Check depencencies' licenses 45 | runs-on: ubuntu-latest 46 | steps: 47 | - name: PyAnsys Licenses Check 48 | uses: ansys/actions/check-licenses@v10 49 | with: 50 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 51 | target: "all" 52 | whitelist-license-check: "attrs,referencing,jeepney" # This has MIT license but fails the check 53 | 54 | docs-style: 55 | name: Documentation Style Check 56 | runs-on: ubuntu-latest 57 | steps: 58 | - name: PyAnsys documentation style checks 59 | uses: ansys/actions/doc-style@v10 60 | with: 61 | token: ${{ secrets.GITHUB_TOKEN }} 62 | 63 | smoke-tests-core: 64 | name: Build core PyAnsys packages 65 | runs-on: ${{ matrix.os }} 66 | strategy: 67 | fail-fast: false 68 | matrix: 69 | os: [windows-latest, ubuntu-latest] 70 | python-version: ['3.10', '3.11', '3.12', '3.13'] 71 | 72 | steps: 73 | - uses: actions/checkout@v4 74 | 75 | - name: Install the latest version of uv and set the python version 76 | uses: astral-sh/setup-uv@v6 77 | with: 78 | python-version: ${{ matrix.python-version }} 79 | cache-dependency-glob: '**/pyproject.toml' 80 | activate-environment: true 81 | 82 | - name: Install core PyAnsys packages 83 | run: | 84 | uv pip install . 85 | 86 | - name: Smoke test 87 | run: python -c "from ${{ env.PACKAGE_NAMESPACE }} import __version__; print(__version__)" 88 | 89 | smoke-tests-extras: 90 | name: Build extras PyAnsys packages 91 | runs-on: ${{ matrix.os }} 92 | needs: [smoke-tests-core] 93 | strategy: 94 | fail-fast: false 95 | matrix: 96 | os: [windows-latest, ubuntu-latest] 97 | python-version: ['3.10', '3.11', '3.12', '3.13'] 98 | extras-version: ['fluent-all', 'mapdl-all', 'tools'] 99 | 100 | steps: 101 | - uses: actions/checkout@v4 102 | 103 | - name: Install the latest version of uv and set the python version 104 | uses: astral-sh/setup-uv@v6 105 | with: 106 | python-version: ${{ matrix.python-version }} 107 | cache-dependency-glob: '**/pyproject.toml' 108 | activate-environment: true 109 | 110 | - name: Install ${{ matrix.extras-version }} PyAnsys packages 111 | run: | 112 | uv pip install .[${{ matrix.extras-version }}] 113 | 114 | - name: Smoke test 115 | run: python -c "from ${{ env.PACKAGE_NAMESPACE }} import __version__; print(__version__)" 116 | 117 | wheelhouse-all: 118 | name: Build PyAnsys package wheelhouse 119 | runs-on: ${{ matrix.os }} 120 | needs: [smoke-tests-core] 121 | strategy: 122 | fail-fast: false 123 | matrix: 124 | os: [windows-latest, ubuntu-latest, macos-latest] 125 | python-version: ['3.10', '3.11', '3.12', '3.13'] 126 | 127 | steps: 128 | - name: Build wheelhouse and perform smoke test 129 | uses: ansys/actions/build-wheelhouse@v10 130 | with: 131 | library-name: ${{ env.PACKAGE_NAME }} 132 | operating-system: ${{ runner.os }} 133 | python-version: ${{ matrix.python-version }} 134 | target: "all" 135 | whitelist-license-check: "attrs,referencing,jeepney" # This has MIT license but fails the check 136 | 137 | - name: List dependencies (pip freeze) 138 | run: | 139 | pip freeze > all-deps-${{ runner.os }}-${{ matrix.python-version }}.txt 140 | cat all-deps-${{ runner.os }}-${{ matrix.python-version }}.txt 141 | 142 | - name: Upload dependencies list 143 | uses: actions/upload-artifact@v4 144 | with: 145 | name: all-deps-${{ runner.os }}-${{ matrix.python-version }} 146 | path: all-deps-${{ runner.os }}-${{ matrix.python-version }}.txt 147 | retention-days: 7 148 | 149 | docs-build: 150 | name: Building Documentation 151 | runs-on: ubuntu-latest 152 | needs: [docs-style] 153 | 154 | steps: 155 | - name: Build documentation 156 | uses: ansys/actions/doc-build@v10 157 | with: 158 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 159 | dependencies: "build-essential zip pandoc texlive-latex-extra latexmk texlive-pstricks" 160 | 161 | doc-deploy-dev: 162 | name: "Deploy development docs" 163 | if: github.ref == 'refs/heads/main' 164 | runs-on: ubuntu-latest 165 | needs: [package] 166 | steps: 167 | - name: Deploy the latest documentation 168 | uses: ansys/actions/doc-deploy-dev@v10 169 | with: 170 | cname: ${{ env.DOCUMENTATION_CNAME }} 171 | token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} 172 | bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} 173 | bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} 174 | 175 | adapt-landing-page-dev: 176 | uses: ./.github/workflows/update-gh-pages.yml 177 | needs: [doc-deploy-dev] 178 | secrets: inherit 179 | 180 | package: 181 | name: Package library 182 | runs-on: ubuntu-latest 183 | needs: [docs-build, smoke-tests-core] 184 | steps: 185 | - name: Build library source and wheel artifacts 186 | uses: ansys/actions/build-library@v10 187 | with: 188 | library-name: ${{ env.PACKAGE_NAME }} 189 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 190 | 191 | release: 192 | name: Release project 193 | if: github.event_name == 'push' && contains(github.ref, 'refs/tags') 194 | needs: [package, smoke-tests-extras, wheelhouse-all] 195 | runs-on: ubuntu-latest 196 | permissions: 197 | contents: write 198 | steps: 199 | - name: Release to PyPI repository 200 | uses: ansys/actions/release-pypi-public@v10 201 | with: 202 | library-name: ${{ env.PACKAGE_NAME }} 203 | twine-username: __token__ 204 | twine-token: ${{ secrets.PYPI_TOKEN }} 205 | 206 | - name: Release to GitHub 207 | uses: ansys/actions/release-github@v10 208 | with: 209 | library-name: ${{ env.PACKAGE_NAME }} 210 | additional-artifacts: 'all-deps-Linux-3.10 all-deps-Linux-3.11 all-deps-Linux-3.12 all-deps-Linux-3.13 all-deps-Windows-3.10 all-deps-Windows-3.11 all-deps-Windows-3.12 all-deps-Windows-3.13 all-deps-macOS-3.10 all-deps-macOS-3.11 all-deps-macOS-3.12 all-deps-macOS-3.13' 211 | token: ${{ secrets.GITHUB_TOKEN }} 212 | 213 | docs-release: 214 | name: Deploy release docs 215 | runs-on: ubuntu-latest 216 | needs: [release] 217 | steps: 218 | - name: Deploy the latest release documentation 219 | uses: ansys/actions/doc-deploy-stable@v10 220 | with: 221 | cname: ${{ env.DOCUMENTATION_CNAME }} 222 | token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} 223 | bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} 224 | bot-email: ${{ secrets.PYANSYS_CI_BOT_EMAIL }} 225 | 226 | adapt-landing-page-release: 227 | uses: ./.github/workflows/update-gh-pages.yml 228 | needs: [docs-release] 229 | secrets: inherit 230 | 231 | automerge-prs: 232 | name: Automerge PRs 233 | runs-on: ubuntu-latest 234 | needs: [package, wheelhouse-all] 235 | if: github.event_name == 'pull_request' 236 | permissions: 237 | contents: write 238 | pull-requests: write 239 | steps: 240 | - name: Automerge PRs 241 | uses: ansys/actions/hk-automerge-prs@v10 242 | with: 243 | approver: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} 244 | approver-token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} 245 | -------------------------------------------------------------------------------- /.github/workflows/create-milestone.yml: -------------------------------------------------------------------------------- 1 | name: Create milestones for Ansys Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | release-date: 6 | description: 'Milestone release date (format must be YYYY/MM/DD)' 7 | required: true 8 | default: '2023/01/30' 9 | 10 | env: 11 | MAIN_PYTHON_VERSION: '3.11' 12 | 13 | jobs: 14 | create-milestone: 15 | name: Create a milestone in ${{ matrix.pyansys-projects }} 16 | runs-on: ubuntu-latest 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | pyansys-projects: 21 | [ 22 | "ansys/pyacp", 23 | "ansys/pyadditive", 24 | "ansys/pyaedt", 25 | "ansys/pyansys-geometry", 26 | "ansys/pyansys-math", 27 | "ansys/pyansys-sound", 28 | "ansys/pyconceptev", 29 | "ansys/pydpf-core", 30 | "ansys/pydpf-post", 31 | "ansys/pydpf-composites", 32 | "ansys/pydyna", 33 | "ansys/pydynamicreporting", 34 | "ansys/pyedb", 35 | "ansys/pyedb-core", 36 | "ansys/pyensight", 37 | "ansys/pyfluent", 38 | "ansys/pygranta", 39 | "ansys/pyhps", 40 | "ansys/pyhps-data-transfer", 41 | "ansys/pymapdl", 42 | "ansys/pymechanical", 43 | "ansys/pymodelcenter", 44 | "ansys/pymotorcad", 45 | "ansys/pyoptislang", 46 | "ansys/pypim", 47 | "ansys/pyprimemesh", 48 | "ansys/pyrocky", 49 | "ansys/pyscadeone", 50 | "ansys/pyseascape", 51 | "ansys/pysherlock", 52 | "ansys/pysimai", 53 | "ansys/pyspeos", 54 | "ansys/pysystem-coupling", 55 | "ansys/pyturbogrid", 56 | "ansys/pytwin", 57 | "ansys/pyworkbench", 58 | # MAPDL - ALL 59 | "ansys/pymapdl-reader", 60 | # FLUENT - ALL 61 | "ansys/pyfluent-visualization", 62 | # TOOLS 63 | "ansys/ansys-tools-filetransfer", 64 | "ansys/ansys-tools-local-product-launcher", 65 | "ansys/ansys-tools-path", 66 | "ansys/ansys-tools-protoc-helper", 67 | "ansys/ansys-tools-visualization-interface", 68 | "ansys/pyansys-tools-report", 69 | "ansys/pyansys-tools-versioning", 70 | "ansys/pyansys-units", 71 | "ansys/pyansys-tools-variableinterop", 72 | "ansys/pymaterials-manager", 73 | ] 74 | steps: 75 | - uses: actions/checkout@v4 76 | 77 | - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} 78 | uses: actions/setup-python@v5 79 | with: 80 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 81 | 82 | - name: Linux pip cache 83 | uses: actions/cache@v4 84 | if: ${{ runner.os == 'Linux' }} 85 | with: 86 | path: ~/.cache/pip 87 | key: Python-${{ runner.os }}-create-milestone 88 | 89 | - name: Install requirements 90 | run: | 91 | pip install pygithub 92 | 93 | - name: Create the milestone 94 | env: 95 | TOKEN: ${{ secrets.CREATE_MILESTONE_TOKEN }} 96 | REPOSITORY: ${{ matrix.pyansys-projects }} 97 | RELEASE_DATE: ${{ github.event.inputs.release-date }} 98 | run: | 99 | python tools/milestone.py 100 | -------------------------------------------------------------------------------- /.github/workflows/update-gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Custom Github pages post-processing 2 | 3 | on: 4 | workflow_dispatch: 5 | workflow_call: 6 | push: 7 | tags: 8 | - "*" 9 | schedule: 10 | - cron: "* 3 * * 5" 11 | 12 | env: 13 | MAIN_PYTHON_VERSION: '3.13' 14 | 15 | jobs: 16 | update-gh-pages: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Install Python 21 | uses: actions/setup-python@v5 22 | with: 23 | python-version: ${{ env.MAIN_PYTHON_VERSION }} 24 | 25 | - name: Install Python dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | python -m pip install requests 29 | 30 | - name: Checkout repository 31 | uses: actions/checkout@v4 32 | 33 | - name: Copy tools folder to /tmp and run sitemap script 34 | working-directory: /tmp 35 | run: | 36 | cp -r /home/runner/work/pyansys/pyansys/tools/ . 37 | python ./tools/catsitemap.py 38 | 39 | - name: Checkout repository gh-pages branch 40 | uses: actions/checkout@v4 41 | with: 42 | ref: gh-pages 43 | 44 | - name: Replace 'version/stable' with 'version/dev' in index.html 45 | run: | 46 | # Replace landing page with the dev version 47 | cp version/dev/index.html index.html 48 | sed -i 's/href="\([^:"]*\)"/href="version\/dev\/\1"/g' index.html 49 | sed -i 's/src="\([^:"]*\)"/src="version\/dev\/\1"/g' index.html 50 | sed -i 's/action="search.html"/action="version\/dev\/\search.html"/g' index.html 51 | # Update JS variables pointing to static values 52 | sed -i 's|const SEARCH_FILE = ".*_static/search.json";|const SEARCH_FILE = "version/dev/_static/search.json";|g' index.html 53 | sed -i 's|const PROJECTS_FILE = "_static/projects.json"|const PROJECTS_FILE = "version/dev/_static/projects.json"|' index.html 54 | # Replace "version/stable" with "version/dev" in the sitemap.xml 55 | sed -i 's/version\/stable/version\/dev/g' sitemap.xml 56 | 57 | - name: Move sitemaps/ to gh-pages root 58 | run: | 59 | rm -rf sitemaps/ && mv /tmp/sitemaps/ . 60 | 61 | - name: "Commit changes" 62 | uses: EndBug/add-and-commit@v9 63 | with: 64 | default_author: github_actions 65 | message: "update index.html and sitemaps folder" 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/python 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=python 3 | 4 | ### Python ### 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | wheelhouse/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | cover/ 58 | .cov 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | db.sqlite3-journal 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | doc/_build/ 79 | doc/**/_autosummary 80 | doc/source/examples/* 81 | doc/source/tmp_pyproject.toml 82 | 83 | # PyBuilder 84 | .pybuilder/ 85 | target/ 86 | 87 | # Jupyter Notebook 88 | .ipynb_checkpoints 89 | 90 | # IPython 91 | profile_default/ 92 | ipython_config.py 93 | 94 | # pyenv 95 | # For a library or package, you might want to ignore these files since the code is 96 | # intended to run in multiple environments; otherwise, check them in: 97 | # .python-version 98 | 99 | # pipenv 100 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 101 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 102 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 103 | # install all needed dependencies. 104 | #Pipfile.lock 105 | 106 | # poetry 107 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 108 | # This is especially recommended for binary packages to ensure reproducibility, and is more 109 | # commonly ignored for libraries. 110 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 111 | #poetry.lock 112 | 113 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 114 | __pypackages__/ 115 | 116 | # Celery stuff 117 | celerybeat-schedule 118 | celerybeat.pid 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | # pytype static type analyzer 151 | .pytype/ 152 | 153 | # Cython debug symbols 154 | cython_debug/ 155 | 156 | #VSCode 157 | .vscode 158 | 159 | # PyCharm 160 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 161 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 162 | # and can be added to the global gitignore or merged into this file. For a more nuclear 163 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 164 | #.idea/ 165 | 166 | # End of https://www.toptal.com/developers/gitignore/api/python 167 | 168 | # Ignore generated project.json file used by documentation 169 | doc/source/_static/projects.json 170 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | 3 | - repo: https://github.com/astral-sh/ruff-pre-commit 4 | rev: v0.11.12 5 | hooks: 6 | - id: ruff 7 | - id: ruff-format 8 | 9 | - repo: https://github.com/codespell-project/codespell 10 | rev: v2.4.1 11 | hooks: 12 | - id: codespell 13 | args: ["--ignore-words=ignore_words.txt"] 14 | 15 | - repo: https://github.com/pycqa/pydocstyle 16 | rev: 6.3.0 17 | hooks: 18 | - id: pydocstyle 19 | additional_dependencies: [toml] 20 | exclude: "tests/" 21 | 22 | - repo: https://github.com/pre-commit/pre-commit-hooks 23 | rev: v5.0.0 24 | hooks: 25 | - id: check-merge-conflict 26 | - id: debug-statements 27 | - id: check-yaml 28 | - id: trailing-whitespace 29 | 30 | # this validates our github workflow files 31 | - repo: https://github.com/python-jsonschema/check-jsonschema 32 | rev: 0.33.0 33 | hooks: 34 | - id: check-github-workflows 35 | 36 | - repo: https://github.com/ansys/pre-commit-hooks 37 | rev: v0.5.2 38 | hooks: 39 | - id: add-license-headers 40 | args: 41 | - --start_year=2022 42 | 43 | - repo: https://github.com/pre-commit/mirrors-prettier 44 | rev: 'v4.0.0-alpha.8' 45 | hooks: 46 | - id: prettier 47 | types_or: [css, javascript] 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 - 2025 ANSYS, Inc. and/or its affiliates. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | PyAnsys metapackage 2 | =================== 3 | |pyansys| |python| |pypi| |downloads| |GH-CI| |MIT| |Ruff| |pre-commit| 4 | 5 | .. |pyansys| image:: https://img.shields.io/badge/Py-Ansys-ffc107.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABDklEQVQ4jWNgoDfg5mD8vE7q/3bpVyskbW0sMRUwofHD7Dh5OBkZGBgW7/3W2tZpa2tLQEOyOzeEsfumlK2tbVpaGj4N6jIs1lpsDAwMJ278sveMY2BgCA0NFRISwqkhyQ1q/Nyd3zg4OBgYGNjZ2ePi4rB5loGBhZnhxTLJ/9ulv26Q4uVk1NXV/f///////69du4Zdg78lx//t0v+3S88rFISInD59GqIH2esIJ8G9O2/XVwhjzpw5EAam1xkkBJn/bJX+v1365hxxuCAfH9+3b9/+////48cPuNehNsS7cDEzMTAwMMzb+Q2u4dOnT2vWrMHu9ZtzxP9vl/69RVpCkBlZ3N7enoDXBwEAAA+YYitOilMVAAAAAElFTkSuQmCC 6 | :target: https://docs.pyansys.com/ 7 | :alt: PyAnsys 8 | 9 | .. |python| image:: https://img.shields.io/pypi/pyversions/pyansys?logo=pypi 10 | :target: https://pypi.org/project/pyansys/ 11 | :alt: Python 12 | 13 | .. |pypi| image:: https://img.shields.io/pypi/v/pyansys.svg?logo=python&logoColor=white 14 | :target: https://pypi.org/project/pyansys/ 15 | :alt: PyPI 16 | 17 | .. |downloads| image:: https://img.shields.io/pypi/dm/pyansys.svg 18 | :target: https://pypi.org/project/pyansys/ 19 | :alt: PyPI Downloads 20 | 21 | .. |GH-CI| image:: https://github.com/ansys/pyansys/actions/workflows/ci-build.yml/badge.svg 22 | :target: https://github.com/ansys/pyansys/actions/workflows/ci-build.yml 23 | :alt: GH-CI 24 | 25 | .. |MIT| image:: https://img.shields.io/badge/License-MIT-yellow.svg 26 | :target: https://opensource.org/licenses/MIT 27 | :alt: MIT 28 | 29 | .. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json 30 | :target: https://github.com/astral-sh/ruff 31 | :alt: Ruff 32 | 33 | .. |pre-commit| image:: https://results.pre-commit.ci/badge/github/pyansys/pyansys/main.svg 34 | :target: https://results.pre-commit.ci/latest/github/pyansys/pyansys/main 35 | :alt: pre-commit.ci status 36 | 37 | Welcome to the PyAnsys metapackage repository. The ``pyansys`` metapackage 38 | provides a single package of collected PyAnsys packages that ensures compatibility 39 | of these packages amongst themselves and the Ansys product release that they are linked to. 40 | 41 | .. image:: https://raw.githubusercontent.com/ansys/pyansys/main/doc/source/_static/pyansys_dark.png 42 | :target: https://docs.pyansys.com 43 | :alt: PyAnsys 44 | 45 | The ``pyansys`` metapackage ensures compatibility between these PyAnsys packages: 46 | 47 | - `PyACP `_: Pythonic interface to Ansys Composite PrepPost (ACP). 48 | - `PyAdditive `_: Pythonic interface to the Ansys Additive service. 49 | - `PyAEDT `_: Pythonic interface to Ansys Electronics Desktop (AEDT). 50 | - `PyAnsys Geometry `_: Pythonic interface to the Ansys Geometry service. 51 | - `PyAnsys Math `_: Pythonic interface to PyAnsys Math libraries. 52 | - `PyAnsys Sound `_: Pythonic interface to Ansys Sound. 53 | - `PyConceptEV `_: Pythonic interface to Ansys ConceptEV library. 54 | - `PyDPF - Core `_: Pythonic interface to the Data Processing Framework (DPF) for building advanced and customized workflows. 55 | - `PyDPF - Post `_: Pythonic interface to access and post process Ansys solver result files. 56 | - `PyDPF - Composites `_: Pythonic interface to postprocess layered and short-fiber composite models. 57 | - `PyDYNA `_: Pythonic interface to build the Ansys DYNA input deck, submit it to the Ansys LS-DYNA solver, and postprocess its results. 58 | - `PyDynamicReporting `_: Pythonic interface to Ansys Dynamic Reporting for service and control of its database and reports. 59 | - `PyEDB `_: Pythonic interface to the Ansys Electronics Database (EDB) client library. 60 | - `PyEDB - Core `_: Pythonic interface to Ansys Electronics Database (EDB). 61 | - `PyEnSight `_: Pythonic interface to EnSight, the Ansys simulation postprocessor. 62 | - `PyFluent `_: Pythonic interface to Ansys Fluent. 63 | - `PyFluent - Visualization `_: Pythonic interface to visualize Ansys Fluent simulations. 64 | - `PyGranta `_: Pythonic interface to Ansys Granta MI services. 65 | - `PyHPS `_: A Python client for Ansys HPC Platform Services (HPS). 66 | - `PyMAPDL `_: Pythonic interface to Ansys MAPDL (Mechanical APDL). 67 | - `PyMAPDL Reader `_: Pythonic interface to read legacy MAPDL result files (MAPDL 14.5 and later). 68 | - `PyMechanical `_: Pythonic interface to Ansys Mechanical. 69 | - `PyModelCenter `_: Pythonic interface for Ansys ModelCenter 70 | - `PyMotorCAD `_: Pythonic interface to Ansys Motor-CAD. 71 | - `PyOptislang `_: Pythonic interface to Ansys optislang. 72 | - `PyPIM `_: Pythonic interface to communicate with the Ansys PIM (Product Instance Management) API. 73 | - `PyPrimeMesh `_: Python library to acquire geometries and prepare surface and volume meshes for multiple solvers. 74 | - `PyRocky `_: Python library to communicate with Ansys Rocky using Rocky PrePost API. 75 | - `PyScadeOne `_: Pythonic interface for Ansys Scade One. 76 | - `PySeascape `_: Pythonic interface to communicate with Ansys RedHawkSC and TotemSC. 77 | - `PySherlock `_: Pythonic interface to communicate with Ansys Sherlock. 78 | - `PySimAI `_: Pythonic interface to use SimAI. 79 | - `PySystemCoupling `_: Pythonic interface to communicate with Ansys System Coupling. 80 | - `PyTurboGrid `_: Pythonic interface to Ansys TurboGrid, a high-quality turbomachinery meshing software app. 81 | - `PyTwin `_: Pythonic interface to communicate with consumption workflows for Ansys digital twins. 82 | - `PyWorkbench `_: Pythonic interface to Ansys Workbench. 83 | - `Shared Components `_: Shared Ansys software components to enable package interoperability and minimize maintenance. 84 | 85 | Other tools delivered as part of the metapackage are: 86 | 87 | - `Ansys FileTransfer Tool `_: Simple gRPC API tool for moving files between a client and a remote server. 88 | - `Ansys Local Product Launcher `_: Python utility for launching Ansys products on a local machine and configuring their launch settings. 89 | - `Ansys Tools Path `_: Library to locate Ansys products in a local machine. 90 | - `Ansys Tools Protobuf Compilation Helper `_: Utility library to compile ``.proto`` files to Python source when building the package wheel. 91 | - `Ansys Tools Visualization Interface `_: Python interface between PyAnsys libraries and plotting backends 92 | - `PyAnsys Tools Report `_: Tool for reporting your Python environment's package versions and hardware resources in a standardized way. 93 | - `PyAnsys Tools Variable Interop `_: Tool for defining basic variables, types, metadata, and values intended to provide interoperability between all products. 94 | - `PyAnsys Tools Versioning `_: Tool for backwards and forwards server support. 95 | - `PyAnsys Units `_: Pythonic interface for units, unit systems, and unit conversions. 96 | - `PyMaterials Manager `_: Python package for unifying material management across the Ansys portfolio. 97 | 98 | Much effort is underway to continue expanding and developing packages in the 99 | `PyAnsys GitHub `__ account. On the ``Issues`` page 100 | for each package, you can post issues and request new features. You can also feel 101 | free to post a question on the `Ansys Developer Forums `_. 102 | 103 | By default, the PyAnsys metapackage installs these core modules: 104 | 105 | - `PyACP`_ 106 | - `PyAdditive`_ 107 | - `PyAEDT`_ 108 | - `PyAnsys Geometry`_ 109 | - `PyAnsys Math`_ 110 | - `PyAnsys Sound`_ 111 | - `PyConceptEV`_ 112 | - `PyDPF - Core`_ 113 | - `PyDPF - Post`_ 114 | - `PyDPF - Composites`_ 115 | - `PyDYNA`_ 116 | - `PyDynamicReporting`_ 117 | - `PyEDB`_ 118 | - `PyEDB - Core`_ 119 | - `PyEnSight`_ 120 | - `PyFluent`_ 121 | - `PyGranta`_ 122 | - `PyHPS`_ 123 | - `PyMAPDL`_ 124 | - `PyMechanical`_ 125 | - `PyMotorCAD`_ 126 | - `PyOptislang`_ 127 | - `PyPIM`_ 128 | - `PyPrimeMesh`_ 129 | - `PyRocky`_ 130 | - `PySeascape`_ 131 | - `PySherlock`_ 132 | - `PySimAI`_ 133 | - `PySystemCoupling`_ 134 | - `PyTurboGrid`_ 135 | - `PyTwin`_ 136 | - `PyWorkbench`_ 137 | - `Shared Components`_ 138 | 139 | Additionally, the ``pyansys`` metapackage contains certain extra targets that 140 | can be installed upon request: 141 | 142 | - **mapdl-all**: This target installs the core packages and `PyMAPDL Reader`_. 143 | - **fluent-all**: This target installs the core packages, and `PyFluent - Visualization`_. 144 | - **tools**: This target installs the core packages, `Ansys FileTransfer Tool`_, `Ansys Local Product Launcher`_, `Ansys Tools Path`_, `Ansys Tools Protobuf Compilation Helper`_, `PyAnsys Tools Report`_, `PyAnsys Tools Variable Interop`_, `PyAnsys Tools Versioning`_, `PyAnsys Units`_, and `PyMaterials Manager`_. 145 | - **all**: This target installs all extra ``pyansys`` packages. 146 | 147 | Package installation 148 | -------------------- 149 | 150 | Two installation modes are provided: user and offline. 151 | 152 | User mode installation 153 | ^^^^^^^^^^^^^^^^^^^^^^ 154 | 155 | Before installing the ``pyansys`` metapackage in user mode, ensure that you have 156 | the latest version of `pip `_ with this command: 157 | 158 | .. code:: bash 159 | 160 | python -m pip install -U pip 161 | 162 | Then, install the ``pyansys`` metapackage with this command: 163 | 164 | .. code:: bash 165 | 166 | python -m pip install pyansys 167 | 168 | If you are interested in **installing an extra target** such as ``fluent-all``, 169 | you use a command like this: 170 | 171 | .. code:: bash 172 | 173 | python -m pip install pyansys[fluent-all] 174 | 175 | If you are interested in **installing a specific version** such as ``2023.1.0``, 176 | you use a command like this: 177 | 178 | .. code:: bash 179 | 180 | python -m pip install pyansys==2023.1.0 181 | 182 | Offline mode installation 183 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 184 | 185 | If you lack an internet connection on your installation machine, the recommended way of installing 186 | the ``pyansys`` metapackage is downloading the wheelhouse archive from the 187 | `Releases Page `_ for your corresponding machine architecture. 188 | 189 | Each wheelhouse archive contains all the Python wheels necessary to install the ``pyansys`` metapackage from 190 | scratch on Windows, Linux, and MacOS from Python 3.10 to 3.13. You can install this on an isolated system with 191 | a fresh Python installation or on a virtual environment. 192 | 193 | For example, on Linux with Python 3.10, unzip the wheelhouse archive and install it with the following 194 | commands: 195 | 196 | .. code:: bash 197 | 198 | unzip pyansys-v2025.1.dev0-wheelhouse-Linux-3.10-core.zip wheelhouse 199 | pip install pyansys -f wheelhouse --no-index --upgrade --ignore-installed 200 | 201 | If you're on Windows with Python 3.10, unzip to a wheelhouse directory and then install using 202 | the same ``pip`` command as in the previous example. 203 | 204 | Consider installing using a `virtual environment `_. 205 | 206 | Versioning system 207 | ----------------- 208 | 209 | The ``pyansys`` metapackage follows a semantic-like versioning system, though it has been adapted to the 210 | Ansys product release mechanism. Thus, this kind of versioning system is followed: 211 | 212 | .. code:: bash 213 | 214 | XXXX.Y.ZZ 215 | 216 | Where: 217 | 218 | - ``XXXX`` is the Ansys product release year (for example, 2022). 219 | - ``Y`` is the Ansys product release within the same year (for example, 1, which relates to R1). 220 | - ``ZZ`` is a patched version to the ``pyansys`` metapackage, if any. 221 | 222 | Consequently, the first ``pyansys`` metapackage compatible with the 2024 R2 release would be: 223 | 224 | .. code:: bash 225 | 226 | 2024.2.0 227 | 228 | Any subsequent patched version of this package would be: 229 | 230 | .. code:: bash 231 | 232 | 2024.2.1 233 | 2024.2.2 234 | 2024.2.3 235 | ... 236 | 237 | You can request a specific version install when using ``pip`` to install 238 | your package: 239 | 240 | .. code:: bash 241 | 242 | python -m pip install pyansys==2024.2.0 243 | 244 | License and acknowledgments 245 | --------------------------- 246 | All PyAnsys libraries are licensed under the MIT license. 247 | 248 | PyAnsys libraries make no commercial claim over Ansys whatsoever. 249 | These libraries extend the functionality of Ansys products by 250 | adding Python interfaces to legally obtained software products 251 | without changing the core behaviors or licenses of the original 252 | software. 253 | 254 | For more information on Ansys products, visit the `Ansys web site `_. 255 | -------------------------------------------------------------------------------- /doc/.vale.ini: -------------------------------------------------------------------------------- 1 | # Core settings 2 | # ============= 3 | 4 | # Location of our `styles` 5 | StylesPath = "styles" 6 | 7 | # The options are `suggestion`, `warning`, or `error` (defaults to “warning”). 8 | MinAlertLevel = warning 9 | 10 | # By default, `code` and `tt` are ignored. 11 | IgnoredScopes = code, tt 12 | 13 | # By default, `script`, `style`, `pre`, and `figure` are ignored. 14 | SkippedScopes = script, style, pre, figure 15 | 16 | # WordTemplate specifies what Vale will consider to be an individual word. 17 | WordTemplate = \b(?:%s)\b 18 | 19 | # List of Packages to be used for our guidelines 20 | Packages = Google 21 | 22 | # Define the Ansys vocabulary 23 | Vocab = ANSYS 24 | 25 | [*.{md,rst}] 26 | 27 | # Apply the following styles 28 | BasedOnStyles = Vale, Google 29 | 30 | # Removing Google-specific rule - Not applicable under some circumstances 31 | Google.WordList = NO 32 | Google.Colons = NO 33 | Vale.Terms = NO 34 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = source 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 20 | 21 | # Customized PDF build 22 | pdf: 23 | @$(SPHINXBUILD) -M latex "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 24 | cd $(BUILDDIR)/latex && latexmk -r latexmkrc -pdf *.tex -interaction=nonstopmode || true 25 | (test -f $(BUILDDIR)/latex/pyansys.pdf && echo pdf exists) || exit 1 26 | 27 | clean: 28 | rm -rf $(BUILDDIR) 29 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /doc/source/_static/css/landing_page.css: -------------------------------------------------------------------------------- 1 | html { 2 | overflow-y: scroll !important; 3 | } 4 | 5 | .landing-page-sidebar { 6 | margin-top: 2rem; 7 | display: flex; 8 | flex-direction: column; 9 | padding: 0rem 2rem; 10 | } 11 | .landing-page-sidebar-section { 12 | margin-bottom: 2rem; 13 | font-weight: 700; 14 | display: flex; 15 | flex-direction: column; 16 | gap: 0.25rem; 17 | } 18 | 19 | .show-more { 20 | margin-top: 1rem; 21 | } 22 | 23 | .landing-page-sidebar-section span { 24 | font-size: 0.85rem; 25 | } 26 | 27 | .family-row, 28 | .tag-row { 29 | display: flex; 30 | align-items: center; 31 | margin: 5px 0; 32 | font-weight: 400; 33 | padding: 0.25rem; 34 | } 35 | 36 | .family-row input, 37 | .tag-row input { 38 | margin-right: 0.625rem; 39 | height: 1rem; 40 | width: 1rem; 41 | } 42 | 43 | .family-count, 44 | .tag-count { 45 | margin-left: auto; 46 | background-color: var(--ast-sidebar-hover-background); 47 | border-radius: 50%; 48 | padding: 0.25rem 0.75rem; 49 | } 50 | .selected-families { 51 | display: flex; 52 | flex-direction: row; 53 | flex-wrap: wrap; 54 | gap: 0.5rem; 55 | } 56 | 57 | .remove-family { 58 | cursor: pointer; 59 | color: black; 60 | font-weight: bold; 61 | } 62 | 63 | .projects { 64 | display: grid; 65 | grid-template-columns: repeat(3, 1fr); 66 | gap: 2rem; 67 | margin-bottom: 1.5rem; 68 | } 69 | 70 | .project-card { 71 | display: flex; 72 | flex-direction: column; 73 | border-radius: 8px; 74 | background-color: white; 75 | } 76 | .project-card:hover { 77 | cursor: pointer; 78 | } 79 | 80 | .project-thumbnail { 81 | padding: 0; 82 | border-top-right-radius: 8px; 83 | border-top-left-radius: 8px; 84 | } 85 | 86 | .project-title { 87 | font-size: 1.2rem; 88 | font-weight: bold; 89 | margin-bottom: 0rem; 90 | padding: 0.5rem; 91 | padding-left: 1rem; 92 | } 93 | 94 | .project-description { 95 | margin-top: 1rem; 96 | padding: 0.5rem; 97 | padding-left: 1rem; 98 | } 99 | .sd-bg-muted { 100 | background-color: var(--ast-sidebar-hover-background) !important; 101 | border-radius: 999px; 102 | font-size: 12px; 103 | line-height: 16px; 104 | } 105 | 106 | [data-theme="dark"] .sd-bg-muted { 107 | background-color: #3d3d3d !important; 108 | } 109 | 110 | @media screen and (max-width: 768px) { 111 | .projects { 112 | grid-template-columns: 1fr; 113 | } 114 | 115 | .landing-page-sidebar { 116 | padding: 1rem; 117 | } 118 | 119 | .project-card { 120 | margin: 0 auto; 121 | width: 90%; 122 | } 123 | } 124 | 125 | .selected-tag, 126 | .selected-family { 127 | display: inline-block; 128 | background-color: var(--ast-sidebar-hover-background); 129 | padding: 0.25rem 0.5rem; 130 | border-radius: 0.25rem; 131 | margin: 0.25em; 132 | font-weight: 600; 133 | } 134 | 135 | .ansys-icon { 136 | width: 1.5rem; 137 | height: 1.5rem; 138 | margin-right: 0.3125rem; 139 | vertical-align: middle; 140 | padding: 0rem; 141 | } 142 | -------------------------------------------------------------------------------- /doc/source/_static/icons/ai-ml.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/source/_static/icons/ansys-icon-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/ansys-icon-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /doc/source/_static/icons/connect.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/design.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /doc/source/_static/icons/digital-twins.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/electromagnetics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/embedded-software.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/fluids.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /doc/source/_static/icons/materials.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/optics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /doc/source/_static/icons/platform.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 81 | -------------------------------------------------------------------------------- /doc/source/_static/icons/semiconductors.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/sound.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/icons/structures.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /doc/source/_static/js/landing_page.js: -------------------------------------------------------------------------------- 1 | function collectFamilies(data) { 2 | const familyData = {}; 3 | 4 | if (!data.projects || typeof data.projects !== "object") { 5 | console.error("Invalid projects data structure:", data.projects); 6 | return familyData; 7 | } 8 | 9 | const projects = Object.values(data.projects); 10 | 11 | for (const project of projects) { 12 | if (!project || typeof project !== "object") continue; 13 | 14 | const family = project.family; 15 | const icon = project.icon || "ansys-icon-light.svg"; // Fallback icon 16 | 17 | if (family) { 18 | if (!familyData[family]) { 19 | familyData[family] = { count: 0, icon: icon }; 20 | } 21 | familyData[family].count += 1; 22 | } 23 | } 24 | 25 | return familyData; 26 | } 27 | 28 | function collectTags(data) { 29 | const tagCounts = {}; 30 | 31 | if (!data.projects || typeof data.projects !== "object") { 32 | console.error("Invalid projects data structure:", data.projects); 33 | return tagCounts; 34 | } 35 | 36 | const projects = Object.values(data.projects); 37 | 38 | for (const project of projects) { 39 | if (!project || typeof project !== "object") continue; 40 | 41 | const tags = project.tags; 42 | 43 | if (Array.isArray(tags)) { 44 | tags.forEach((tag) => { 45 | tagCounts[tag] = (tagCounts[tag] || 0) + 1; 46 | }); 47 | } 48 | } 49 | 50 | return tagCounts; 51 | } 52 | 53 | function displayFamilies(familyData) { 54 | const familiesContainer = document.getElementById("product-families-list"); 55 | familiesContainer.innerHTML = ""; 56 | 57 | const sortedFamilies = Object.keys(familyData).sort(); 58 | const maxVisible = 5; 59 | let showMoreClicked = false; 60 | const theme = document.documentElement.dataset.theme || "light"; 61 | 62 | sortedFamilies.forEach((family, index) => { 63 | const { count, icon } = familyData[family]; 64 | 65 | const familyRow = document.createElement("div"); 66 | familyRow.className = "family-row"; 67 | if (index >= maxVisible) familyRow.style.display = "none"; // Hide extra items initially 68 | 69 | const checkbox = document.createElement("input"); 70 | checkbox.type = "checkbox"; 71 | checkbox.id = `family-${CSS.escape(family)}`; 72 | checkbox.addEventListener("change", handleFamilySelection); 73 | 74 | const familyName = document.createElement("span"); 75 | familyName.className = "family-name"; 76 | familyName.textContent = family; 77 | 78 | const iconImage = document.createElement("img"); 79 | iconImage.alt = `${family} icon`; 80 | iconImage.className = "ansys-icon"; 81 | let basePath = "version/dev/"; 82 | if (window.location.pathname.includes("version/dev")) { 83 | basePath = ""; 84 | } else if (window.location.pathname.includes("version/stable")) { 85 | // If the path is versioned, default to current page 86 | basePath = ""; 87 | } else { 88 | // If the path is not versioned, default to dev 89 | basePath = "version/dev/"; 90 | } 91 | 92 | const iconName = 93 | theme === "dark" && icon === "ansys-icon-light.svg" 94 | ? "ansys-icon-dark.svg" 95 | : `${icon}`; 96 | 97 | iconImage.src = `${basePath}${iconName}`; 98 | 99 | const familyCountElement = document.createElement("span"); 100 | familyCountElement.className = "family-count"; 101 | familyCountElement.textContent = `${count}`; 102 | 103 | familyRow.appendChild(checkbox); 104 | familyRow.appendChild(iconImage); 105 | familyRow.appendChild(familyName); 106 | familyRow.appendChild(familyCountElement); 107 | 108 | familiesContainer.appendChild(familyRow); 109 | }); 110 | 111 | // Handle "Show more" click 112 | const showMoreButton = document.querySelector(".product-families .show-more"); 113 | const FamilyRows = document.querySelectorAll(".family-row"); 114 | showMoreButton.addEventListener("click", () => { 115 | if (showMoreClicked) { 116 | FamilyRows.forEach((row, index) => { 117 | if (index >= maxVisible) { 118 | row.style.display = "none"; 119 | } 120 | }); 121 | showMoreButton.textContent = "Show more"; 122 | showMoreClicked = false; 123 | } else { 124 | FamilyRows.forEach((row) => { 125 | row.style.display = "flex"; 126 | }); 127 | showMoreButton.textContent = "Show less"; 128 | showMoreClicked = true; 129 | } 130 | }); 131 | } 132 | 133 | function displayTags(tagCounts) { 134 | const tagsContainer = document.getElementById("product-tags-list"); 135 | tagsContainer.innerHTML = ""; 136 | 137 | const sortedTags = Object.keys(tagCounts).sort(); 138 | const maxVisible = 5; // Show only first 5 initially 139 | let showMoreClicked = false; 140 | 141 | sortedTags.forEach((tag, index) => { 142 | const tagCount = tagCounts[tag]; 143 | 144 | const tagRow = document.createElement("div"); 145 | tagRow.className = "tag-row"; 146 | if (index >= maxVisible) tagRow.style.display = "none"; // Hide extra items initially 147 | 148 | const checkbox = document.createElement("input"); 149 | checkbox.type = "checkbox"; 150 | checkbox.id = `tag-${CSS.escape(tag)}`; 151 | checkbox.addEventListener("change", handleTagSelection); 152 | 153 | const tagName = document.createElement("span"); 154 | tagName.className = "tag-name"; 155 | tagName.textContent = tag; 156 | 157 | const tagCountElement = document.createElement("span"); 158 | tagCountElement.className = "tag-count"; 159 | tagCountElement.textContent = `${tagCount}`; 160 | 161 | tagRow.appendChild(checkbox); 162 | tagRow.appendChild(tagName); 163 | tagRow.appendChild(tagCountElement); 164 | 165 | tagsContainer.appendChild(tagRow); 166 | }); 167 | 168 | // Handle "Show more" click 169 | const showMoreButton = document.querySelector(".product-tags .show-more"); 170 | const TagRows = document.querySelectorAll(".tag-row"); 171 | showMoreButton.addEventListener("click", () => { 172 | if (showMoreClicked) { 173 | TagRows.forEach((row, index) => { 174 | if (index >= maxVisible) { 175 | row.style.display = "none"; 176 | } 177 | }); 178 | showMoreButton.textContent = "Show more"; 179 | showMoreClicked = false; 180 | } else { 181 | TagRows.forEach((row) => { 182 | row.style.display = "flex"; 183 | }); 184 | showMoreButton.textContent = "Show less"; 185 | showMoreClicked = true; 186 | } 187 | }); 188 | } 189 | 190 | function handleFamilySelection() { 191 | applyFilters(); 192 | } 193 | 194 | function handleTagSelection() { 195 | applyFilters(); 196 | } 197 | 198 | function applyFilters() { 199 | const SelectedTagsContainer = document.getElementById( 200 | "selected-product-tags-list", 201 | ); 202 | const SelectedFamiliesContainer = document.getElementById( 203 | "selected-product-families-list", 204 | ); 205 | SelectedTagsContainer.innerHTML = ""; 206 | SelectedFamiliesContainer.innerHTML = ""; 207 | const selectedFamilies = Array.from( 208 | document.querySelectorAll( 209 | '#product-families-list input[type="checkbox"]:checked', 210 | ), 211 | ).map((checkbox) => 212 | checkbox.id.replace("family-", "").replace("\\ ", "-").toLowerCase(), 213 | ); 214 | 215 | const selectedTags = Array.from( 216 | document.querySelectorAll( 217 | '#product-tags-list input[type="checkbox"]:checked', 218 | ), 219 | ).map((checkbox) => 220 | checkbox.id.replace("tag-", "").replace("\\ ", "-").toLowerCase(), 221 | ); 222 | for (const tag of selectedTags) { 223 | const selectedTag = document.createElement("span"); 224 | selectedTag.className = "selected-tag"; 225 | selectedTag.textContent = tag; 226 | SelectedTagsContainer.appendChild(selectedTag); 227 | } 228 | 229 | for (const family of selectedFamilies) { 230 | const selectedFamily = document.createElement("span"); 231 | selectedFamily.className = "selected-family"; 232 | selectedFamily.textContent = family; 233 | SelectedFamiliesContainer.appendChild(selectedFamily); 234 | } 235 | 236 | console.log("Selected families:", selectedFamilies); 237 | console.log("Selected tags:", selectedTags); 238 | 239 | const projectCards = document.querySelectorAll(".project-card"); 240 | 241 | projectCards.forEach((card) => { 242 | const family = card.getAttribute("data-family").toLowerCase(); 243 | const rawTags = card.getAttribute("data-tags"); 244 | 245 | let cardTags = []; 246 | if (rawTags) { 247 | try { 248 | cardTags = JSON.parse(rawTags.replace(/'/g, '"')).map((tag) => 249 | tag.toLowerCase(), 250 | ); 251 | } catch (error) { 252 | console.error("Error parsing data-tags:", rawTags, error); 253 | } 254 | } 255 | 256 | // Check if the card matches the selected families 257 | const matchesAllFamilies = 258 | selectedFamilies.length === 0 || selectedFamilies.includes(family); 259 | 260 | // Check if the card matches the selected tags 261 | const matchesAllTags = 262 | selectedTags.length === 0 || 263 | selectedTags.every((tag) => cardTags.includes(tag)); 264 | 265 | // Show only if both family & tag filters match (or if no filter is applied) 266 | card.style.display = matchesAllFamilies && matchesAllTags ? "flex" : "none"; 267 | }); 268 | } 269 | 270 | function initializeAllCards() { 271 | const articleElement = document.querySelector("article"); 272 | const projects = articleElement.querySelectorAll(".project-card"); 273 | projects.forEach((project) => { 274 | project.style.display = "flex"; 275 | }); 276 | } 277 | 278 | document.addEventListener("DOMContentLoaded", () => { 279 | fetch(PROJECTS_FILE) 280 | .then((response) => { 281 | if (!response.ok) { 282 | throw new Error(`HTTP error! Status: ${response.status}`); 283 | } 284 | return response.json(); 285 | }) 286 | .then((data) => { 287 | // Display families 288 | const familyData = collectFamilies(data); 289 | displayFamilies(familyData); 290 | 291 | // Display tags 292 | const tagCounts = collectTags(data); 293 | displayTags(tagCounts); 294 | 295 | // Render all cards 296 | initializeAllCards(); 297 | }) 298 | .catch((error) => { 299 | console.error("Error fetching the projects data:", error); 300 | }); 301 | }); 302 | 303 | function updateIcon() { 304 | theme = document.documentElement.dataset.theme || "light"; 305 | let icons = document.querySelectorAll(".ansys-icon"); 306 | 307 | if (icons) { 308 | icons.forEach((iconImage) => { 309 | if (theme === "dark" && iconImage.src.includes("ansys-icon-light.svg")) { 310 | iconImage.src = iconImage.src.replace( 311 | "ansys-icon-light.svg", 312 | "ansys-icon-dark.svg", 313 | ); 314 | } 315 | if (theme === "light" && iconImage.src.includes("ansys-icon-dark.svg")) { 316 | iconImage.src = iconImage.src.replace( 317 | "ansys-icon-dark.svg", 318 | "ansys-icon-light.svg", 319 | ); 320 | } 321 | }); 322 | } 323 | } 324 | 325 | const observer = new MutationObserver(updateIcon); 326 | observer.observe(document.documentElement, { 327 | attributes: true, 328 | attributeFilter: ["data-theme"], 329 | }); 330 | 331 | // Initial call to set the icon on page load 332 | updateIcon(); 333 | -------------------------------------------------------------------------------- /doc/source/_static/pyansys_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/pyansys_dark.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/5gwizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/5gwizard.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/ansys-python-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/ansys-python-manager.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/intro.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyacp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyacp.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyaedt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyaedt.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyansys-cheat-sheets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyansys-cheat-sheets.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyansys-common.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyansys-common.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyansys-geometry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyansys-geometry.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyansys-math.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyansys-math.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyansys-sound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyansys-sound.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyconceptev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyconceptev.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pydpf-composites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pydpf-composites.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pydpf-core.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pydpf-core.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pydpf-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pydpf-post.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pydyna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pydyna.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pydynamicreporting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pydynamicreporting.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyedb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyedb.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyensight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyensight.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyfluent-parametric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyfluent-parametric.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyfluent-visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyfluent-visualization.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyfluent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyfluent.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pygranta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pygranta.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymapdl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymapdl.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymapdl_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymapdl_dark.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymapdl_reader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymapdl_reader.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymechanical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymechanical.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymodelcenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymodelcenter.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pymotorcad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pymotorcad.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyoptislang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyoptislang.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyprimemesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyprimemesh.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyrocky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyrocky.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyscadeone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyscadeone.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pysherlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pysherlock.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pysimai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pysimai.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyspeos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyspeos.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pysystem-coupling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pysystem-coupling.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pyturbogrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pyturbogrid.png -------------------------------------------------------------------------------- /doc/source/_static/thumbnails/pytwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/source/_static/thumbnails/pytwin.png -------------------------------------------------------------------------------- /doc/source/_templates/landing_page_sidebar.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | Product families 6 |
7 |
8 | Show more 9 |
10 | 11 |
12 | 13 | 14 |
15 | Tags 16 |
17 |
18 | Show more 19 |
20 | 21 |
22 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /doc/source/api.rst: -------------------------------------------------------------------------------- 1 | API reference 2 | ============= 3 | 4 | The ``pyansys`` metapackage on its own does not have a specific API. The only information specific-only 5 | to this package that can be provided is its version. This can be looked up as follows: 6 | 7 | .. code-block:: pycon 8 | 9 | >>> from pyansys import __version__ 10 | >>> __version__ 11 | 12 | '2023.1.0' 13 | 14 | However, each of the PyAnsys packages that shape the ``pyansys`` metapackage have their own specific API 15 | reference section. In order to navigate through them, please refer to their documentation. 16 | 17 | ****************************** 18 | PyAnsys packages API reference 19 | ****************************** 20 | 21 | .. jinja:: project_context 22 | 23 | .. grid:: 3 24 | :gutter: 3 3 4 4 25 | 26 | {% for project, metadata in projects['projects'].items() %} 27 | {% if 'Tools' not in metadata['family'] %} 28 | .. grid-item-card:: {{ metadata['name'] }} 29 | :img-top: {{ metadata['thumbnail'] }} 30 | :link: {{ metadata['documentation']['api'] }} 31 | :class-title: pyansys-card-title 32 | 33 | {% endif %} 34 | {% endfor %} -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | """Configuration file for docs.pyansys.com landing page.""" 2 | 3 | from datetime import datetime 4 | import json 5 | import os 6 | from pathlib import Path 7 | import subprocess 8 | 9 | from ansys_sphinx_theme import ansys_favicon, get_version_match 10 | import github 11 | from PIL import Image 12 | import requests 13 | import sphinx 14 | from sphinx.builders.latex import LaTeXBuilder 15 | import toml 16 | import yaml 17 | 18 | from pyansys import __version__ as pyansys_version 19 | 20 | # Declare constants 21 | GENERATED_DIR = Path(__file__).parent / "package_versions" 22 | 23 | VERSIONS_TEMPLATE = """ 24 | Package versions in PyAnsys {{ version }} 25 | ============================{{ "=" * version|length }} 26 | 27 | The PyAnsys packages delivered in version {{ version }} are: 28 | {{ ' ' }} 29 | {%- for entry in table %} 30 | {{ entry }} 31 | {%- endfor %} 32 | """ 33 | 34 | INDEX_TEMPLATE = """ 35 | Package versions 36 | ================ 37 | 38 | Users can find below the list of PyAnsys packages available in the various 39 | PyAnsys metapackages. The tables shows the package versions available in each 40 | metapackage release. 41 | 42 | .. toctree:: 43 | :maxdepth: 3 44 | {{ ' ' }} 45 | {%- for version in versions %} 46 | version_{{ version }} 47 | {%- endfor %} 48 | """ 49 | 50 | TMP_FILE = Path("tmp_pyproject.toml") 51 | 52 | LaTeXBuilder.supported_image_types = [ 53 | "image/png", 54 | "image/pdf", 55 | "image/svg+xml", 56 | ] # noqa: E501 57 | 58 | project = "pyansys" 59 | copyright = f"(c) {datetime.now().year} ANSYS, Inc. All rights reserved" 60 | author = "ANSYS Inc." 61 | cname = os.getenv("DOCUMENTATION_CNAME", default="nocname.com") 62 | switcher_version = get_version_match(pyansys_version) 63 | 64 | # Get the PyAnsys version 65 | release = version = pyansys_version 66 | 67 | html_theme = "ansys_sphinx_theme" 68 | html_short_title = html_title = "PyAnsys" 69 | 70 | # Favicon 71 | html_favicon = ansys_favicon 72 | 73 | html_sidebars = { 74 | "index": ["landing_page_sidebar.html"], 75 | } 76 | 77 | extensions = [ 78 | "sphinx_design", 79 | "sphinx_copybutton", 80 | "sphinxcontrib.mermaid", 81 | "sphinx_jinja", 82 | ] 83 | 84 | # Static files 85 | templates_path = ["_templates"] 86 | html_static_path = ["_static"] 87 | html_css_files = ["css/landing_page.css"] 88 | 89 | metadata = Path(__file__).parent.parent.parent / "projects.yaml" 90 | 91 | 92 | def read_dependencies_from_pyproject(): 93 | """Read the dependencies declared in the project file.""" 94 | pyproject = Path(__file__).parent.parent.parent / "pyproject.toml" 95 | if not pyproject.exists(): 96 | raise ValueError(f"The file {pyproject} does not exist.") 97 | 98 | pyproject_content = toml.loads(pyproject.read_text(encoding="utf-8")) 99 | dependencies = pyproject_content["project"]["dependencies"] 100 | return {pkg.split("==")[0]: pkg.split("==")[1] for pkg in dependencies} 101 | 102 | 103 | def read_optional_dependencies_from_pyproject(): 104 | """Read the extra dependencies declared in the project file.""" 105 | pyproject = Path(__file__).parent.parent.parent / "pyproject.toml" 106 | if not pyproject.exists(): 107 | raise ValueError(f"The file {pyproject} does not exist.") 108 | 109 | pyproject_content = toml.loads(pyproject.read_text(encoding="utf-8")) 110 | exclude_targets = ["doc"] 111 | optional_dependencies = { 112 | target: {pkg.split("==")[0]: pkg.split("==")[1] for pkg in deps} 113 | for target, deps in pyproject_content["project"]["optional-dependencies"].items() 114 | if target not in exclude_targets 115 | } 116 | return optional_dependencies 117 | 118 | 119 | def get_last_metapackage_release(): 120 | """Retrieve the last release of the metapackage.""" 121 | # Get the PyAnsys metapackage repository 122 | g = github.Github(os.getenv("GITHUB_TOKEN", None)) 123 | repository = g.get_repo("ansys/pyansys") 124 | 125 | # Get the last release 126 | last_release = repository.get_latest_release() 127 | 128 | return last_release.tag_name 129 | 130 | 131 | jinja_globals = { 132 | "LAST_RELEASE": get_last_metapackage_release(), 133 | "VERSION": version, 134 | "SUPPORTED_PYTHON_VERSIONS": ["3.10", "3.11", "3.12", "3.13"], 135 | "SUPPORTED_PLATFORMS": ["Windows", "macOS", "Linux"], 136 | } 137 | jinja_contexts = { 138 | "project_context": {"projects": yaml.safe_load(metadata.read_text(encoding="utf-8"))}, 139 | "dependencies": {"dependencies": read_dependencies_from_pyproject()}, 140 | "optional_dependencies": {"optional_dependencies": read_optional_dependencies_from_pyproject()}, 141 | "wheelhouse": { 142 | "wheelhouse": { 143 | platform: icon 144 | for platform, icon in zip(["Windows", "macOS", "Linux"], ["windows", "apple", "linux"]) 145 | } 146 | }, 147 | } 148 | 149 | html_context = { 150 | "github_user": "ansys", 151 | "github_repo": "pyansys", 152 | "github_version": "main", 153 | "doc_path": "doc/source", 154 | "page_assets": { 155 | "getting-started/prerequisites": { 156 | "needs_datatables": True, 157 | }, 158 | "getting-started/install": { 159 | "needs_datatables": True, 160 | }, 161 | }, 162 | } 163 | 164 | html_theme_options = { 165 | "logo": "pyansys", 166 | "github_url": "https://github.com/ansys/pyansys", 167 | "show_prev_next": False, 168 | "show_breadcrumbs": True, 169 | "collapse_navigation": True, 170 | "use_edit_page_button": True, 171 | "icon_links": [ 172 | { 173 | "name": "Support", 174 | "url": "https://github.com/ansys/pyansys/discussions", 175 | "icon": "fa fa-comment fa-fw", 176 | }, 177 | { 178 | "name": "Contribute", 179 | "url": "https://dev.docs.pyansys.com/how-to/contributing.html", 180 | "icon": "fa fa-wrench", 181 | }, 182 | ], 183 | "switcher": { 184 | "json_url": f"https://{cname}/versions.json", 185 | "version_match": switcher_version, 186 | }, 187 | "check_switcher": False, 188 | "static_search": { 189 | "threshold": 0.5, 190 | "min_chars_for_search": 2, 191 | "ignoreLocation": True, 192 | }, 193 | } 194 | 195 | # Check all references work fine 196 | nitpicky = True 197 | 198 | # The suffix(es) of source filenames. 199 | source_suffix = ".rst" 200 | 201 | # The master toctree document. 202 | master_doc = "index" 203 | 204 | exclude_patterns = [ 205 | "_build", 206 | "Thumbs.db", 207 | ".DS_Store", 208 | "links.rst", 209 | ] 210 | 211 | # Read link all targets from file 212 | path_to_links_rst = Path(__file__).parent / "links.rst" 213 | rst_epilog = path_to_links_rst.read_text(encoding="utf-8") 214 | 215 | # Ignore certain URLs 216 | linkcheck_ignore = [ 217 | r"https://www.ansys.com.*", 218 | rf"https://pypi.org/project/pyansys/{switcher_version}.*", 219 | r"https://ansunits.docs.*", 220 | r"https://download.ansys.com/.*", 221 | r"https://github.com/ansys/pyansys/releases/download/*", 222 | ] 223 | 224 | # User agent 225 | user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.2420.81" # noqa: E501 226 | 227 | 228 | ########################################################################### 229 | 230 | # ------------------------------------------------------------------------- 231 | # Defining Sphinx build hooks 232 | # ------------------------------------------------------------------------- 233 | 234 | ########################################################################### 235 | # Generate the package_versions directory 236 | ########################################################################### 237 | # This section generates the package_versions directory in the doc/source 238 | # directory. This directory contains the .rst files that list the PyAnsys 239 | # package versions available in the various PyAnsys metapackages releases. 240 | # 241 | # The script retrieves the PyAnsys package versions from the pyproject.toml 242 | # file for the minor versions of the PyAnsys metapackage release branches. 243 | 244 | 245 | def get_documentation_link_from_pypi(library: str, version: str) -> str: 246 | """Get the documentation link from PyPI for a specific library and version.""" 247 | # Get the PyPI metadata for the library 248 | resp = requests.get(f"https://pypi.org/pypi/{library}/{version}/json") 249 | metadata = resp.json() 250 | 251 | # Get the documentation URL 252 | default_url = f"https://pypi.org/project/{library}/{version}" 253 | try: 254 | project_urls = metadata["info"]["project_urls"] 255 | url = None 256 | for tag in [ 257 | "Documentation", 258 | "Homepage", 259 | "Source", 260 | ]: # Prefer Documentation, then Homepage, then Source... 261 | url = project_urls.get(tag) 262 | if url: 263 | break 264 | 265 | return url if url else default_url 266 | except (KeyError, AttributeError): 267 | return default_url 268 | 269 | 270 | def pyansys_multiversion_docs_link(docs_link: str, version: str) -> str: 271 | """Verify if the documentation link is a multi-version link. 272 | 273 | Notes 274 | ----- 275 | Checks if the documentation link is a multi-version link. If it is, it 276 | tries to access the documentation for the specific version. In case of 277 | failure, it returns the default link. This is done on a best effort basis. 278 | 279 | """ 280 | # First, let's check it is an official PyAnsys documentation link 281 | if "docs.pyansys.com" in docs_link: 282 | # Clean the link 283 | tmp_link = docs_link.split("docs.pyansys.com")[0] + "docs.pyansys.com" 284 | # Get the major.minor version 285 | major_minor_version = ".".join(version.split(".")[:2]) 286 | 287 | # Attempt to access the documentation for the specific version 288 | try: 289 | resp = requests.get(f"{tmp_link}/version/{major_minor_version}/index.html") 290 | if resp.status_code == 200: 291 | return f"{tmp_link}/version/{major_minor_version}" 292 | except requests.exceptions.RequestException: 293 | pass 294 | 295 | # Fall back to the default link 296 | return docs_link 297 | 298 | 299 | def build_versions_table(branch: str) -> list[str]: 300 | """Build the versions table for the PyAnsys libraries.""" 301 | # Download the pyproject.toml file 302 | resp = requests.get(f"https://raw.githubusercontent.com/ansys/pyansys/{branch}/pyproject.toml") 303 | with TMP_FILE.open("wb") as file: 304 | file.write(resp.content) 305 | 306 | # Load the pyproject.toml file using TOML parser 307 | pyproject_toml = toml.load(TMP_FILE) 308 | 309 | # Check if it is poetrty based or flit based and 310 | # load the PyAnsys library versions 311 | list_pyansys_libraries: list[str] = [] 312 | if "poetry" in pyproject_toml["tool"]: # Assume poetry 313 | for key, val in pyproject_toml["tool"]["poetry"]["dependencies"].items(): 314 | # Ignore some libraries 315 | if key in ["python", "importlib-metadata", "Sphinx"]: 316 | continue 317 | 318 | # Check if the version is a string or a dictionary... 319 | if ( 320 | isinstance(val, dict) 321 | and isinstance(val["version"], str) 322 | and val["version"].startswith("==") 323 | ): 324 | list_pyansys_libraries.append(f"{key}{val['version']}") 325 | elif isinstance(val, str) and val.startswith("=="): 326 | list_pyansys_libraries.append(f"{key}{val}") 327 | else: 328 | continue 329 | else: # Assume flit 330 | list_pyansys_libraries += pyproject_toml["project"]["dependencies"] 331 | list_pyansys_libraries += pyproject_toml["project"]["optional-dependencies"]["all"] 332 | 333 | # Ignore some libraries: in this case, only importlib-metadata 334 | list_pyansys_libraries = [ 335 | entry for entry in list_pyansys_libraries if not entry.startswith("importlib-metadata") 336 | ] 337 | 338 | # Delete the temporary file 339 | TMP_FILE.unlink() 340 | 341 | # Build the table 342 | table = [] 343 | 344 | # Add the header 345 | dict_table_entries: dict[str, str] = {} 346 | for entry in list_pyansys_libraries: 347 | library, version = entry.split("==") 348 | pypi_link = f"https://pypi.org/project/{library}/{version}" 349 | docs_link = get_documentation_link_from_pypi(library, version) 350 | 351 | # EXPERIMENTAL: Let's see if we can point to the actual version documentation... 352 | docs_link = pyansys_multiversion_docs_link(docs_link, version) 353 | 354 | dict_table_entries[library] = ( 355 | f"`{library} <{docs_link}>`__", 356 | f"`{version} <{pypi_link}>`__", 357 | ) 358 | 359 | # Get the max length of the library and versions columns 360 | libcol_size = max(len(entry[0]) for entry in dict_table_entries.values()) 361 | vercol_size = max(len(entry[1]) for entry in dict_table_entries.values()) 362 | 363 | # Format the table entries and headers 364 | table = [] 365 | separator = f"+-{'-' * libcol_size}-+-{'-' * vercol_size}-+" 366 | table.append(separator) 367 | table.append(f"| {'Library'.ljust(libcol_size)} | {'Version'.ljust(vercol_size)} |") 368 | table.append(f"+={'=' * libcol_size}=+={'=' * vercol_size}=+") 369 | for library, entry in dict_table_entries.items(): 370 | table.append(f"| {entry[0].ljust(libcol_size)} | {entry[1].ljust(vercol_size)} |") 371 | table.append(separator) 372 | 373 | return table 374 | 375 | 376 | ########################################################################### 377 | # Adapting thumbnails to the documentation 378 | ########################################################################### 379 | # This section adapts the thumbnails to the documentation. The thumbnails 380 | # are resized to 640x480 pixels and centered on a white background. 381 | # 382 | # The script resizes all images in the _static/thumbnails directory to 640x480 383 | # pixels and saves the resized images in the same directory. After the 384 | # documentation build, the script reverts the changes to the thumbnails. 385 | 386 | 387 | def resize_with_background(input_image_path, output_image_path, target_size): 388 | """Resize an image while maintaining aspect ratio and centering it on a white background. 389 | 390 | Parameters 391 | ---------- 392 | input_image_path : Path 393 | The path to the input image. 394 | output_image_path : Path 395 | The path to save the output image. 396 | target_size : tuple[int, int] 397 | The target size of the output image as a tuple (width, height) in pixels. 398 | """ 399 | # Open the input image 400 | img = Image.open(input_image_path).convert("RGBA") # Ensure the image has an alpha channel 401 | 402 | # Resize the image while maintaining aspect ratio 403 | img.thumbnail(target_size, Image.LANCZOS) 404 | 405 | # Create a white background of the target size 406 | background = Image.new( 407 | "RGBA", target_size, (255, 255, 255, 255) 408 | ) # White background with no transparency 409 | 410 | # Calculate the position to center the resized image on the background 411 | img_w, img_h = img.size 412 | bg_w, bg_h = background.size 413 | offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2) 414 | 415 | # Paste the resized image onto the white background 416 | background.paste(img, offset, mask=img) # Use the image's transparency as a mask 417 | 418 | # Convert the image to RGB to remove the alpha channel (no transparency) 419 | background = background.convert("RGB") 420 | 421 | # Save the result to the output path 422 | background.save(output_image_path) 423 | 424 | 425 | ########################################################################### 426 | 427 | # -------------------------------------------------------------------------- 428 | # Sphinx build hooks 429 | # -------------------------------------------------------------------------- 430 | 431 | 432 | def resize_thumbnails(app: sphinx.application.Sphinx): 433 | """Resize all images in the current directory to 640x480 pixels.""" 434 | # Process all images 435 | 436 | thumbnail_dir = Path(__file__).parent.absolute() / "_static" / "thumbnails" 437 | 438 | for image in thumbnail_dir.glob("*.png"): 439 | target_size = (640, 480) 440 | resize_with_background(image, image, target_size) 441 | 442 | 443 | def revert_thumbnails(app: sphinx.application.Sphinx, exception): 444 | """Resize all images in the current directory to 640x480 pixels.""" 445 | thumbnail_dir = Path(__file__).parent.absolute() / "_static" / "thumbnails" 446 | 447 | subprocess.run(["git", "checkout", "--", thumbnail_dir]) 448 | 449 | 450 | def convert_yaml_to_json(app: sphinx.application.Sphinx): 451 | """ 452 | Convert a YAML file to a JSON file. 453 | 454 | Parameters: 455 | yaml_path (Path): Path to the YAML file. 456 | json_path (Path): Path to save the JSON file. 457 | 458 | Returns: 459 | None 460 | """ 461 | if not metadata.exists() or not metadata.is_file(): 462 | raise FileNotFoundError(f"The file {metadata} does not exist or is not a file.") 463 | 464 | with metadata.open("r", encoding="utf-8") as yaml_file: 465 | try: 466 | yaml_content = yaml.safe_load(yaml_file) 467 | except yaml.YAMLError as e: 468 | raise ValueError(f"Error parsing YAML file: {e}") 469 | 470 | json_path = Path(__file__).parent / "_static" / "projects.json" 471 | with json_path.open("w", encoding="utf-8") as json_file: 472 | json.dump(yaml_content, json_file, indent=4) 473 | print(f"JSON file successfully written to {json_path}") 474 | 475 | 476 | def fetch_release_branches_and_python_limits(app: sphinx.application.Sphinx): 477 | """Retrieve the release branches in the PyAnsys metapackage.""" 478 | # Get the PyAnsys metapackage repository 479 | g = github.Github(os.getenv("GITHUB_TOKEN", None)) 480 | repository = g.get_repo("ansys/pyansys") 481 | 482 | # Get the branches 483 | branches = repository.get_branches() 484 | 485 | supported_python_versions_by_metapackage_version = [] 486 | for branch in branches: 487 | if not branch.name.startswith("release") and not branch.name.startswith("main"): 488 | continue 489 | 490 | # Inspect the pyproject.toml file to get the Python limits 491 | pyproject = repository.get_contents("pyproject.toml", ref=branch.name) 492 | content = toml.loads(pyproject.decoded_content.decode("utf-8")) 493 | 494 | # Extract the latest version and the Python limits 495 | branch_name = branch.name 496 | metapackage_version = branch_name.split("/")[-1] 497 | try: 498 | pypi_version = content["project"]["version"] 499 | python_limits = content["project"]["requires-python"].split(",") 500 | except KeyError: 501 | pypi_version = content["tool"]["poetry"]["version"] 502 | python_limits = content["tool"]["poetry"]["dependencies"]["python"].split(",") 503 | 504 | if pypi_version.split(".")[-1].startswith("dev"): 505 | link = repository.html_url 506 | else: 507 | link = f"https://pypi.org/project/pyansys/{pypi_version}" 508 | 509 | supported_python_versions_by_metapackage_version.append( 510 | { 511 | "version": metapackage_version, 512 | "python": {"lower": python_limits[0], "upper": python_limits[1]}, 513 | "link": link, 514 | } 515 | ) 516 | 517 | print(supported_python_versions_by_metapackage_version) 518 | 519 | jinja_contexts["releases"] = {"table_data": supported_python_versions_by_metapackage_version} 520 | 521 | 522 | def setup(app: sphinx.application.Sphinx): 523 | """Run different hook functions during the documentation build. 524 | 525 | Parameters 526 | ---------- 527 | app : sphinx.application.Sphinx 528 | Sphinx instance containing all the configuration for the documentation build. 529 | """ 530 | # At the beginning of the build process - update the version in cheatsheet 531 | app.connect("builder-inited", convert_yaml_to_json) 532 | app.connect("builder-inited", resize_thumbnails) 533 | app.connect("builder-inited", fetch_release_branches_and_python_limits) 534 | 535 | # Reverting the thumbnails - no local changes 536 | app.connect("build-finished", revert_thumbnails) 537 | -------------------------------------------------------------------------------- /doc/source/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | Examples for the different ``pyansys`` packages can be found in their specific documentation. 5 | 6 | ************************* 7 | PyAnsys packages examples 8 | ************************* 9 | 10 | .. note:: Combining PyAnsys libraries? 11 | 12 | If you are using multiple PyAnsys libraries, you can find examples on how to combine them 13 | in the `PyAnsys Workflows `_ page. This page contains 14 | practical examples on how to chain different PyAnsys libraries together. 15 | 16 | .. jinja:: project_context 17 | 18 | .. grid:: 3 19 | :gutter: 3 3 4 4 20 | 21 | {% for project, metadata in projects['projects'].items() %} 22 | {% if 'Tools' not in metadata['family'] %} 23 | .. grid-item-card:: {{ metadata['name'] }} 24 | :img-top: {{ metadata['thumbnail'] }} 25 | :link: {{ metadata['documentation']['examples'] }} 26 | :class-title: pyansys-card-title 27 | 28 | {% endif %} 29 | {% endfor %} -------------------------------------------------------------------------------- /doc/source/getting-started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | This page helps you quickly get started with PyAnsys. It lists all the 5 | prerequisites and guides you step by step to install the project on your 6 | platform. 7 | 8 | .. grid:: 1 1 3 3 9 | 10 | .. grid-item-card:: :fa:`info-circle` About PyAnsys 11 | :link: getting-started/about 12 | :link-type: doc 13 | :padding: 2 2 2 2 14 | 15 | Learn more about PyAnsys and its ecosystem 16 | 17 | .. grid-item-card:: :fa:`tasks` Prerequisites 18 | :link: getting-started/prerequisites 19 | :link-type: doc 20 | :padding: 2 2 2 2 21 | 22 | What you need prior installing PyAnsys 23 | 24 | .. grid-item-card:: :fa:`download` Install 25 | :link: getting-started/install 26 | :link-type: doc 27 | :padding: 2 2 2 2 28 | 29 | Guidelines on how to install PyAnsys in your system 30 | 31 | .. toctree:: 32 | :maxdepth: 3 33 | :hidden: 34 | 35 | About 36 | Prerequisites 37 | Install 38 | 39 | -------------------------------------------------------------------------------- /doc/source/getting-started/about.rst: -------------------------------------------------------------------------------- 1 | About 2 | ##### 3 | 4 | PyAnsys is a collection of Python libraries and tools developed by `ANSYS, 5 | Inc.`_ It provides access to `Ansys products`_ by using a Python interface, 6 | enabling users to perform engineering simulations, data processing, and 7 | automation tasks. 8 | 9 | To ease the installation of the libraries and tools, PyAnsys provides a Python 10 | metapackage. This ensures compatibility between its projects. 11 | 12 | Key features of PyAnsys 13 | ======================= 14 | 15 | PyAnsys shines in the following areas: 16 | 17 | - **Automation of workflows:** PyAnsys enables users to automate repetitive or 18 | complex simulation tasks. 19 | 20 | - **Integration with the Python ecosystem:** users can leverage the Python 21 | ecosystem. 22 | 23 | - **Cross-product functionality:** PyAnsys provides Python APIs for various 24 | Ansys services and products. By allowing users to interact with multiple 25 | products in a single environment, PyAnsys enables users to streamline their 26 | workflows. 27 | 28 | The PyAnsys ecosystem 29 | ===================== 30 | 31 | PyAnsys libraries can be classified into wrappers and tools. 32 | 33 | **Wrappers** are Python libraries that provide direct access to Ansys products. 34 | Communication between the product and the library is performed via `gRPC 35 | `_. Therefore, users can have the product installed remotely and connect 36 | to that remote instance. 37 | 38 | **Tools** are Python libraries that provide additional functionality to the 39 | wrappers. 40 | -------------------------------------------------------------------------------- /doc/source/getting-started/install.rst: -------------------------------------------------------------------------------- 1 | Install PyAnsys 2 | ############### 3 | 4 | The PyAnsys metapackage is distributed as a Python library. Its installation 5 | follows the standard Python package installation process. 6 | 7 | Online installation 8 | =================== 9 | 10 | Download and install PyAnsys from `PyPI`_: 11 | 12 | .. tab-set:: 13 | 14 | .. tab-item:: :fab:`windows` **Windows** 15 | 16 | .. code-block:: bash 17 | 18 | python -m pip install pyansys 19 | 20 | .. tab-item:: :fab:`apple` **MacOS** 21 | 22 | .. code-block:: bash 23 | 24 | python -m pip install pyansys 25 | 26 | .. tab-item:: :fab:`linux` **Linux** 27 | 28 | .. code-block:: bash 29 | 30 | python -m pip install pyansys 31 | 32 | The PyAnsys |version| metapackage includes the following projects: 33 | 34 | .. jinja:: dependencies 35 | 36 | .. raw:: html 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {% for project, version in dependencies.items() %} 55 | 56 | 57 | 58 | 59 | {% endfor %} 60 | 61 |
PyAnsys projectVersion
{{ project }}{{ version }}
62 | 63 | Additional targets 64 | ------------------ 65 | 66 | The PyAnsys metapackage contains various targets for installing additional 67 | libraries and tools. 68 | 69 | .. jinja:: optional_dependencies 70 | 71 | .. tab-set:: 72 | 73 | {% for target, dependencies in optional_dependencies.items() %} 74 | 75 | .. tab-item:: {{ target }} 76 | 77 | Install by running: 78 | 79 | .. code-block:: bash 80 | 81 | python -m pip install pyansys[{{ target }}] 82 | 83 | .. raw:: html 84 | 85 | 86 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | {% for project, version in dependencies.items() %} 102 | 103 | 104 | 105 | 106 | {% endfor %} 107 | 108 |
PyAnsys projectVersion
{{ project }}{{ version }}
109 | 110 | 111 | 112 | 113 | {% endfor %} 114 | 115 | 116 | Offline installation 117 | ==================== 118 | 119 | Start by downloading the wheelhouse artifact for your platform: 120 | 121 | .. jinja:: wheelhouse 122 | 123 | .. csv-table:: 124 | :header-rows: 1 125 | :widths: 16, 28, 28, 28, 28 126 | 127 | :fas:`laptop` Platform, 128 | {%- for python in SUPPORTED_PYTHON_VERSIONS -%} 129 | :fab:`python` Python {{ python }} 130 | {%- if not loop.last -%},{%- endif -%} 131 | {% endfor %} 132 | {% for platform, icon in wheelhouse.items() -%} 133 | :fab:`{{ icon }}` {{ platform }}, 134 | {%- for python in SUPPORTED_PYTHON_VERSIONS -%} 135 | {%- if "dev" in VERSION -%} 136 | `Download wheelhouse `__ 137 | {%- else -%} 138 | `Download wheelhouse `__ 139 | {%- endif -%} 140 | {%- if not loop.last -%},{%- endif -%} 141 | {% endfor %} 142 | {% endfor %} 143 | 144 | Next, decompress the artifacts: 145 | 146 | .. code-block:: bash 147 | 148 | unzip wheelhouse 149 | 150 | Finally, install the PyAnsys metapackage using previously downloaded wheelhouse: 151 | 152 | .. code-block:: bash 153 | 154 | python -m pip install pyansys -f wheelhouse --no-index --upgrade --ignore-installed 155 | -------------------------------------------------------------------------------- /doc/source/getting-started/prerequisites.rst: -------------------------------------------------------------------------------- 1 | Prerequisites 2 | ############# 3 | 4 | You need to have the following prerequisites to get started with PyAnsys: 5 | 6 | - A valid Python version 7 | - A licensed version of Ansys 8 | 9 | Download and install Ansys 10 | ========================== 11 | 12 | Download Ansys software from the `Ansys Customer Portal`_. Ensure you have a 13 | license to use the software. 14 | 15 | Download and install Python 16 | =========================== 17 | 18 | Download and install the latest stable version of Python from the 19 | `https://www.python.org/downloads `_. 20 | 21 | Supported Python versions 22 | ------------------------- 23 | 24 | The PyAnsys ecosystem follows `SPEC-0`_ for Python version support. This 25 | implies that PyAnsys packages drop support for a Python version three years 26 | after their initial release: 27 | 28 | .. mermaid:: 29 | :caption: Python versions supported by SPEC-0 policy (red line) and PyAnsys Python versions supported (color coded) 30 | :alt: Current Python versions supported by the PyAnsys metapackage 31 | :align: center 32 | 33 | gantt 34 | dateFormat YYYY-MM-DD 35 | axisFormat %Y-%m 36 | Python 3.7 :done, des1, 2018-06-27, 3y 37 | Python 3.8 :done, des2, 2019-10-14, 3y 38 | Python 3.9 :done, des3, 2020-10-05, 3y 39 | Python 3.10 :active, des4, 2021-10-04, 3y 40 | Python 3.11 :active, des5, 2022-10-24, 3y 41 | Python 3.12 :active, des6, 2023-10-02, 3y 42 | Python 3.13 :active, des7, 2024-10-01, 3y 43 | Python 3.14 :, des8, 2025-10-07, 3y 44 | 45 | In previous diagram: 46 | 47 | * Python versions in gray are no longer supported 48 | * Python versions in light blue are currently supported 49 | * Python versions in dark blue are not supported yet 50 | 51 | .. note:: 52 | 53 | Adoption and deprecation of Python versions in the PyAnsys ecosystem are 54 | tentative. Delays may occur due to third party dependencies. 55 | 56 | Below you can find a list of the Python versions supported by each PyAnsys 57 | metapackage release: 58 | 59 | .. jinja:: releases 60 | 61 | .. raw:: html 62 | 63 | 64 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | {% for release in table_data %} 82 | 83 | 84 | 85 | 86 | 87 | 88 | {% endfor %} 89 | 90 |
PyAnsys versionMin. Python versionMax. Python versionDownload
{{ release.version }}{{ release.python.lower }}{{ release.python.upper }}{{ release.link }}
91 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | PyAnsys 3 | ======= 4 | 5 | Welcome to the PyAnsys project. While this project originated as a single ``pyansys`` package, 6 | it is now a collection of many Python packages for using Ansys products through Python: 7 | 8 | .. toctree:: 9 | :hidden: 10 | :maxdepth: 3 11 | 12 | getting-started 13 | user_guide 14 | api 15 | examples 16 | tools/index 17 | 18 | .. jinja:: project_context 19 | 20 | .. raw:: html 21 | 22 |
23 | {% for project, metadata in projects['projects'].items() %} 24 | 25 | {% set family = metadata.get('family', 'other') | lower | replace(' ', '-') %} 26 | {% set tags = metadata.get('tags', 'other') | lower %} 27 | 28 |
34 | 35 |
36 |

{{ metadata['name'] }}

37 |

{{ metadata['description'] }}

38 |

39 | {{ family.capitalize() }} 40 | {% for tag in metadata['tags'] %} 41 | {{ tag }} 42 | {% endfor %} 43 |

44 |
45 |
46 | 47 | {% endfor %} 48 |
49 | -------------------------------------------------------------------------------- /doc/source/links.rst: -------------------------------------------------------------------------------- 1 | .. Getting started 2 | .. _mapdl_course: https://www.ansys.com/training-center/course-catalog/structures/ansys-mechanical-advanced-use-of-mapdl-in-mechanical 3 | .. _ansys_fluent_page: https://www.ansys.com/products/fluids/ansys-fluent 4 | .. _ansys_aedt_page: https://www.ansys.com/products/electronics/ansys-maxwell 5 | .. _dpf_post_gh: https://github.com/ansys/pydpf-post 6 | .. _grpc: https://grpc.io/ 7 | .. _ansys_students: https://www.ansys.com/academic/students 8 | .. _pip: https://pypi.org/project/pip/ 9 | .. _pyansys_releases: https://github.com/ansys/pyansys/releases 10 | .. _venv_docs: https://docs.python.org/3/library/venv.html 11 | 12 | .. ANSYS and products 13 | .. _ANSYS, Inc.: https://www.ansys.com 14 | .. _Ansys products: https://www.ansys.com/products 15 | .. _Ansys Customer Portal: https://download.ansys.com 16 | 17 | .. Python libraries 18 | .. _PyPI: https://pypi.org/ 19 | .. _Numpy: https://numpy.org/ 20 | .. _SciPy: https://www.scipy.org/ 21 | .. _Pandas: https://pandas.pydata.org/ 22 | .. _Matplotlib: https://matplotlib.org/ 23 | .. _PyVista: https://docs.pyvista.org/ 24 | .. _Pydata Sphinx Theme: https://pydata-sphinx-theme.readthedocs.io/en/stable/ 25 | 26 | .. PEPs, NEPs, and SPECs 27 | .. _NEP 29: https://numpy.org/neps/nep-0029-deprecation_policy.html 28 | .. _SPEC-0: https://scientific-python.org/specs/spec-0000/ 29 | 30 | -------------------------------------------------------------------------------- /doc/source/tools/index.rst: -------------------------------------------------------------------------------- 1 | Other tools 2 | =========== 3 | 4 | Standalone projects, tooling libraries and toolkits related to the PyAnsys ecosystem. 5 | 6 | .. grid:: 1 7 | :gutter: 3 3 4 4 8 | 9 | .. grid-item-card:: :octicon:`package` Standalone projects 10 | :link: standalone/index 11 | :link-type: doc 12 | 13 | Standalone projects to exploit the full potential of the PyAnsys ecosystem 14 | 15 | .. grid-item-card:: :octicon:`tools` Tooling libraries 16 | :link: libraries/index 17 | :link-type: doc 18 | 19 | Additional libraries delivered with the ``tools`` target of the PyAnsys metapackage 20 | 21 | .. grid-item-card:: :octicon:`gear` Toolkits 22 | :link: toolkits/index 23 | :link-type: doc 24 | 25 | Toolkits built on top of PyAnsys libraries for specific purposes. 26 | 27 | .. toctree:: 28 | :hidden: 29 | 30 | standalone/index 31 | libraries/index 32 | toolkits/index -------------------------------------------------------------------------------- /doc/source/tools/libraries/index.rst: -------------------------------------------------------------------------------- 1 | Tooling libraries 2 | ================= 3 | 4 | .. grid:: 3 5 | :gutter: 3 3 4 4 6 | 7 | .. grid-item-card:: Ansys FileTransfer Tool 8 | :img-top: ../../_static/thumbnails/intro.png 9 | :link: https://filetransfer.tools.docs.pyansys.com/version/stable 10 | :class-title: pyansys-card-title 11 | 12 | Simple gRPC API tool for moving files between a client and a remote server 13 | 14 | .. grid-item-card:: Ansys Local Product Launcher 15 | :img-top: ../../_static/thumbnails/intro.png 16 | :link: https://local-product-launcher.tools.docs.pyansys.com/version/stable 17 | :class-title: pyansys-card-title 18 | 19 | Python utility for launching Ansys products on a local machine and configuring their launch settings 20 | 21 | .. grid-item-card:: Ansys Tools Path 22 | :img-top: ../../_static/thumbnails/intro.png 23 | :link: https://path.tools.docs.pyansys.com/version/stable 24 | :class-title: pyansys-card-title 25 | 26 | Library to locate Ansys products in a local machine 27 | 28 | .. grid-item-card:: Ansys Tools Protobuf Compilation Helper 29 | :img-top: ../../_static/thumbnails/intro.png 30 | :link: https://ansys.github.io/ansys-tools-protoc-helper/ 31 | :class-title: pyansys-card-title 32 | 33 | Utility library to compile ``.proto`` files to Python source when building the package wheel 34 | 35 | .. grid-item-card:: Ansys Tools Visualization interface 36 | :img-top: ../../_static/thumbnails/intro.png 37 | :link: https://visualization-interface.tools.docs.pyansys.com/version/stable 38 | :class-title: pyansys-card-title 39 | 40 | Python interface between PyAnsys libraries and plotting backends 41 | 42 | .. grid-item-card:: PyAnsys Tools Report 43 | :img-top: ../../_static/thumbnails/intro.png 44 | :link: https://report.tools.docs.pyansys.com/version/stable 45 | :class-title: pyansys-card-title 46 | 47 | Tool for reporting your Python environment's package versions and hardware resources in a standardized way 48 | 49 | .. grid-item-card:: PyAnsys Tools Variable Interop 50 | :img-top: ../../_static/thumbnails/intro.png 51 | :link: https://variableinterop.docs.pyansys.com/version/stable 52 | :class-title: pyansys-card-title 53 | 54 | Tool for defining basic variables, types, metadata, and values intended to provide interoperability between all products 55 | 56 | .. grid-item-card:: PyAnsys Tools Versioning 57 | :img-top: ../../_static/thumbnails/intro.png 58 | :link: https://versioning.tools.docs.pyansys.com/version/stable 59 | :class-title: pyansys-card-title 60 | 61 | Tool for backwards and forwards server support 62 | 63 | .. grid-item-card:: PyAnsys Units 64 | :img-top: ../../_static/thumbnails/intro.png 65 | :link: https://units.docs.pyansys.com/version/stable 66 | :class-title: pyansys-card-title 67 | 68 | Pythonic interface for units, unit systems, and unit conversions 69 | 70 | .. grid-item-card:: PyMaterials Manager 71 | :img-top: ../../_static/thumbnails/intro.png 72 | :link: https://manager.materials.docs.pyansys.com/version/stable 73 | :class-title: pyansys-card-title 74 | 75 | Python package for unifying material management across the Ansys portfolio 76 | -------------------------------------------------------------------------------- /doc/source/tools/standalone/index.rst: -------------------------------------------------------------------------------- 1 | Standalone projects 2 | =================== 3 | 4 | .. contents:: 5 | 6 | General purpose 7 | --------------- 8 | 9 | .. jinja:: project_context 10 | 11 | .. grid:: 3 12 | :gutter: 3 3 4 4 13 | 14 | {% for project, metadata in projects['projects'].items() %} 15 | {% if 'General purpose' in metadata['tags'] %} 16 | .. grid-item-card:: {{ metadata['name'] }} 17 | :img-top: ../../{{ metadata['thumbnail'] }} 18 | :link: {{ metadata['documentation']['base'] }} 19 | :class-title: pyansys-card-title 20 | 21 | {{ metadata['description'] }} 22 | {% endif %} 23 | {% endfor %} 24 | 25 | Demo purposes 26 | ------------- 27 | 28 | .. jinja:: project_context 29 | 30 | .. grid:: 3 31 | :gutter: 3 3 4 4 32 | 33 | {% for project, metadata in projects['projects'].items() %} 34 | {% if 'Demo' in metadata['tags'] %} 35 | .. grid-item-card:: {{ metadata['name'] }} 36 | :img-top: ../../{{ metadata['thumbnail'] }} 37 | :link: {{ metadata['documentation']['base'] }} 38 | :class-title: pyansys-card-title 39 | 40 | {{ metadata['description'] }} 41 | {% endif %} 42 | {% endfor %} 43 | 44 | Repository management 45 | --------------------- 46 | 47 | .. jinja:: project_context 48 | 49 | .. grid:: 3 50 | :gutter: 3 3 4 4 51 | 52 | {% for project, metadata in projects['projects'].items() %} 53 | {% if 'Repository management' in metadata['tags'] %} 54 | .. grid-item-card:: {{ metadata['name'] }} 55 | :img-top: ../../{{ metadata['thumbnail'] }} 56 | :link: {{ metadata['documentation']['base'] }} 57 | :class-title: pyansys-card-title 58 | 59 | {{ metadata['description'] }} 60 | {% endif %} 61 | {% endfor %} 62 | 63 | Artificial intelligence 64 | ----------------------- 65 | 66 | .. jinja:: project_context 67 | 68 | .. grid:: 3 69 | :gutter: 3 3 4 4 70 | 71 | {% for project, metadata in projects['projects'].items() %} 72 | {% if 'Artificial intelligence' in metadata['tags'] %} 73 | .. grid-item-card:: {{ metadata['name'] }} 74 | :img-top: ../../{{ metadata['thumbnail'] }} 75 | :link: {{ metadata['documentation']['base'] }} 76 | :class-title: pyansys-card-title 77 | 78 | {{ metadata['description'] }} 79 | {% endif %} 80 | {% endfor %} 81 | 82 | Documentation 83 | ------------- 84 | 85 | .. jinja:: project_context 86 | 87 | .. grid:: 3 88 | :gutter: 3 3 4 4 89 | 90 | {% for project, metadata in projects['projects'].items() %} 91 | {% if 'Documentation' in metadata['tags'] %} 92 | .. grid-item-card:: {{ metadata['name'] }} 93 | :img-top: ../../{{ metadata['thumbnail'] }} 94 | :link: {{ metadata['documentation']['base'] }} 95 | :class-title: pyansys-card-title 96 | 97 | {{ metadata['description'] }} 98 | {% endif %} 99 | {% endfor %} 100 | -------------------------------------------------------------------------------- /doc/source/tools/toolkits/index.rst: -------------------------------------------------------------------------------- 1 | PyAnsys toolkits 2 | ================ 3 | 4 | .. contents:: 5 | 6 | PyAEDT toolkits 7 | --------------- 8 | .. jinja:: project_context 9 | 10 | .. grid:: 3 11 | :gutter: 3 3 4 4 12 | 13 | {% for project, metadata in projects['projects'].items() %} 14 | {% if 'PyAEDT toolkits' in metadata['tags'] %} 15 | .. grid-item-card:: {{ metadata['name'] }} 16 | :img-top: ../../{{ metadata['thumbnail'] }} 17 | :link: {{ metadata['documentation']['base'] }} 18 | :class-title: pyansys-card-title 19 | 20 | {{ metadata['description'] }} 21 | {% endif %} 22 | {% endfor %} -------------------------------------------------------------------------------- /doc/source/user_guide.rst: -------------------------------------------------------------------------------- 1 | User guide 2 | ========== 3 | 4 | User guides for the different ``pyansys`` packages can be found in their specific documentation. 5 | The ``pyansys`` metapackage itself has no functionalities on its own. It is only a bundle of the 6 | different public PyAnsys libraries that are compatible with a given Ansys Unified Install depending 7 | on the version requested. 8 | 9 | **************************** 10 | PyAnsys packages user guides 11 | **************************** 12 | 13 | .. jinja:: project_context 14 | 15 | .. grid:: 3 16 | :gutter: 3 3 4 4 17 | 18 | {% for project, metadata in projects['projects'].items() %} 19 | {% if 'Tools' not in metadata['family'] %} 20 | .. grid-item-card:: {{ metadata['name'] }} 21 | :img-top: {{ metadata['thumbnail'] }} 22 | :link: {{ metadata['documentation']['user_guide'] }} 23 | :class-title: pyansys-card-title 24 | {% endif %} 25 | {% endfor %} -------------------------------------------------------------------------------- /doc/styles/.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | !**/ANSYS/accept.txt 3 | !**/ANSYS/reject.txt 4 | !.gitignore -------------------------------------------------------------------------------- /doc/styles/config/vocabularies/ANSYS/accept.txt: -------------------------------------------------------------------------------- 1 | ANSYS 2 | Ansys 3 | ansys 4 | API 5 | postprocessing 6 | PyAnsys 7 | (?i)Python 8 | Pythonic 9 | PyAEDT 10 | DPF 11 | PyMAPDL 12 | PyMAPDL Reader 13 | PyDPF - Core 14 | PyDPF - Post 15 | PyDPF - Composites 16 | PyDPF 17 | PyFluent 18 | PyPIM 19 | metapackage 20 | PyTwin 21 | toolkits 22 | -------------------------------------------------------------------------------- /doc/styles/config/vocabularies/ANSYS/reject.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansys/pyansys/fd55c8ae22ce2e019d007d5c8d9b7b1076184dcc/doc/styles/config/vocabularies/ANSYS/reject.txt -------------------------------------------------------------------------------- /ignore_words.txt: -------------------------------------------------------------------------------- 1 | parm 2 | pres 3 | WAN 4 | filname 5 | ans 6 | tread 7 | wan 8 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=3.2,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [project] 6 | # Check https://flit.readthedocs.io/en/latest/pyproject_toml.html for all available sections 7 | name = "pyansys" 8 | version = "2025.1.dev0" 9 | description = "Pythonic interfaces to Ansys products" 10 | readme = "README.rst" 11 | requires-python = ">=3.10,<4" 12 | license = { file = "LICENSE" } 13 | authors = [{ name = "ANSYS, Inc.", email = "pyansys.support@ansys.com" }] 14 | maintainers = [{ name = "PyAnsys developers", email = "pyansys.maintainers@ansys.com" }] 15 | classifiers = [ 16 | "Development Status :: 4 - Beta", 17 | "Intended Audience :: Science/Research", 18 | "Topic :: Scientific/Engineering :: Information Analysis", 19 | "License :: OSI Approved :: MIT License", 20 | "Operating System :: OS Independent", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: 3.11", 23 | "Programming Language :: Python :: 3.12", 24 | "Programming Language :: Python :: 3.13", 25 | ] 26 | 27 | dependencies = [ 28 | "ansys-acp-core==0.2.0", 29 | "ansys-additive-core==0.20.0", 30 | "ansys-conceptev-core==0.9.4", 31 | "ansys-dpf-composites==0.7.0", 32 | "ansys-dpf-core==0.13.8", 33 | "ansys-dpf-post==0.9.3", 34 | "ansys-dyna-core==0.8.0", 35 | "ansys-dynamicreporting-core==0.10.1", 36 | "ansys-edb-core==0.1.10", 37 | "ansys-fluent-core==0.32.1", 38 | "ansys-geometry-core==0.10.9", 39 | "ansys-hps-client==0.10.1", 40 | "ansys-hps-data-transfer-client==0.2.1", 41 | "ansys-mapdl-core==0.70.1", 42 | "ansys-math-core==0.2.4", 43 | "ansys-mechanical-core==0.11.18", 44 | "ansys-meshing-prime==0.8.1", 45 | "ansys-modelcenter-workflow==0.1.1", 46 | "ansys-motorcad-core==0.7.2", 47 | "ansys-optislang-core==1.0.0", 48 | "ansys-platform-instancemanagement==1.1.2", 49 | "ansys-pyensight-core==0.10.3", 50 | "ansys-rocky-core==0.3.2", 51 | "ansys-seascape==0.2.0", 52 | "ansys-sherlock-core==0.9.0", 53 | "ansys-simai-core==0.3.0", 54 | "ansys-sound-core==0.1.3", 55 | "ansys-speos-core==0.5.1", 56 | "ansys-systemcoupling-core==0.9.0", 57 | "ansys-turbogrid-core==0.4.5", 58 | "ansys-workbench-core==0.9.0", 59 | "pyaedt==0.17.0", 60 | "pyedb==0.50.0", 61 | "pygranta==2025.1.0", 62 | "pytwin==0.9.2", 63 | ] 64 | 65 | [project.optional-dependencies] 66 | mapdl-all = ["ansys-mapdl-reader==0.55.1"] 67 | fluent-all = ["ansys-fluent-visualization==0.20.0"] 68 | tools = [ 69 | "ansys-materials-manager==0.2.3", 70 | "ansys-tools-filetransfer==0.1.1", 71 | "ansys-tools-local-product-launcher==0.1.1", 72 | "ansys-tools-path==0.7.1", 73 | # "ansys-tools-protoc-helper==0.4.0; python_version<='3.10'", 74 | "ansys-tools-visualization-interface==0.9.2", 75 | "ansys-units==0.6.0", 76 | "pyansys-tools-report==0.8.2", 77 | "pyansys-tools-versioning==0.6.0", 78 | "pyansys-tools-variableinterop==0.1.1", 79 | ] 80 | all = [ 81 | # MAPDL - ALL 82 | "ansys-mapdl-reader==0.55.1", 83 | # FLUENT - ALL 84 | "ansys-fluent-visualization==0.20.0", 85 | # TOOLS 86 | "ansys-materials-manager==0.2.3", 87 | "ansys-tools-filetransfer==0.1.1", 88 | "ansys-tools-local-product-launcher==0.1.1", 89 | "ansys-tools-path==0.7.1", 90 | # "ansys-tools-protoc-helper==0.4.0; python_version<='3.10'", 91 | "ansys-tools-visualization-interface==0.9.2", 92 | "ansys-units==0.6.0", 93 | "pyansys-tools-report==0.8.2", 94 | "pyansys-tools-versioning==0.6.0", 95 | "pyansys-tools-variableinterop==0.1.1", 96 | ] 97 | doc = [ 98 | "Sphinx==8.2.3", 99 | "ansys-sphinx-theme==1.5.2", 100 | "Jinja2 ==3.1.6", 101 | "Pillow==11.2.1", 102 | "PyGithub==2.6.1", 103 | "sphinx-copybutton==0.5.2", 104 | "sphinx-design==0.6.1", 105 | "sphinxcontrib-mermaid==1.0.0", 106 | "sphinx-jinja==2.0.2", 107 | ] 108 | 109 | [project.urls] 110 | Source = "https://github.com/ansys/pyansys" 111 | Documentation = "https://docs.pyansys.com" 112 | 113 | [tool.flit.module] 114 | name = "pyansys" 115 | 116 | [tool.ruff] 117 | line-length = 100 118 | fix = true 119 | 120 | [tool.ruff.format] 121 | quote-style = "double" 122 | indent-style = "space" 123 | docstring-code-format = true 124 | docstring-code-line-length = "dynamic" 125 | 126 | [tool.ruff.lint] 127 | select = [ 128 | "E", # pycodestyle, see https://docs.astral.sh/ruff/rules/#pycodestyle-e-w 129 | "F", # pyflakes, see https://docs.astral.sh/ruff/rules/#pyflakes-f 130 | "I", # isort, see https://docs.astral.sh/ruff/rules/#isort-i 131 | "N", # pep8-naming, see https://docs.astral.sh/ruff/rules/#pep8-naming-n 132 | "PTH", # flake8-use-pathlib, https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth 133 | "TD", # flake8-todos, https://docs.astral.sh/ruff/rules/#flake8-todos-td 134 | ] 135 | ignore = [ 136 | "TD002", # Missing author in TODOs comment 137 | ] 138 | 139 | [tool.ruff.lint.pydocstyle] 140 | convention = "numpy" 141 | 142 | [tool.ruff.lint.isort] 143 | combine-as-imports = true 144 | force-sort-within-sections = true 145 | -------------------------------------------------------------------------------- /src/pyansys/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. 2 | # SPDX-License-Identifier: MIT 3 | # 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | """PyAnsys general package __init__ file.""" 24 | 25 | import importlib.metadata as importlib_metadata 26 | 27 | # Read from the pyproject.toml 28 | # major, minor, patch 29 | __version__ = importlib_metadata.version("pyansys") 30 | -------------------------------------------------------------------------------- /tools/catsitemap.py: -------------------------------------------------------------------------------- 1 | """Script for automatic generation/download of sitemaps for pyansys projects. 2 | 3 | Intended for the pyansys project and to be used with the update-gh-pages 4 | workflow. 5 | 6 | """ 7 | 8 | from pathlib import Path 9 | from xml.dom import minidom 10 | import xml.etree.ElementTree as ET 11 | 12 | from links import LINKS 13 | import requests 14 | 15 | 16 | def download_file(url: str, dest_path: Path) -> None: 17 | """Given a sitemap url, this function downloads the file into (dest_path). 18 | 19 | Parameters 20 | ---------- 21 | url : str 22 | The url of the sitemap file to be downloaded 23 | dest_path : Path 24 | The destination path to save the downloaded file 25 | 26 | Raises 27 | ------ 28 | requests.exceptions.Timeout 29 | Raises this exception when accessing a link takes too long 30 | """ 31 | # Send the request 32 | response = requests.get(url, stream=True, timeout=30) 33 | 34 | # Write the file content to the specified location 35 | with dest_path.open(mode="w", encoding="utf-8") as file: 36 | file.write(response.text) 37 | 38 | 39 | def extract_urls_and_headers(links_dict: dict) -> tuple: 40 | """Extract valid project names and sitemap urls from metadata dictionary. 41 | 42 | Parameters 43 | ---------- 44 | links_dict : dict 45 | Dictionary containing metadata of projects 46 | 47 | Returns 48 | ------- 49 | tuple 50 | Contains the list of project names and the list of sitemap urls 51 | """ 52 | valid_project_names = [] 53 | valid_urls = [] 54 | for project_name, url in links_dict.items(): 55 | # The form of url is "https://subdomain.docs.pyansys.com/version/stable 56 | # where subdomain may contain nested subdomains depending on the project 57 | # see links.py from which LINKS was imported for examples 58 | if url is None: 59 | continue 60 | # url is changed to "https://subdomain.docs.pyansys.com/sitemap.xml 61 | # this is general form of the link to the sitemap file of each project 62 | updated_url = url.split("docs.pyansys.com")[0] + "docs.pyansys.com/sitemap.xml" 63 | if requests.get(url).status_code == 404: 64 | continue 65 | else: 66 | valid_project_names.append(project_name) 67 | valid_urls.append(updated_url) 68 | 69 | return valid_project_names, valid_urls 70 | 71 | 72 | def generate_sitemap_index(project_names: list, dest_path: Path) -> None: 73 | """Generate the global sitemap file which will point to all other sitemaps. 74 | 75 | Parameters 76 | ---------- 77 | project_names : list 78 | List of project names with a downloadable sitemap file 79 | dest_path : Path 80 | The destination path to save the generated sitemap file 81 | """ 82 | # Create the root element with namespace 83 | sitemap_index = ET.Element("sitemapindex", xmlns="http://www.sitemaps.org/schemas/sitemap/0.9") 84 | 85 | # Create sitemap elements for each URL 86 | for project in project_names: 87 | # Modify the url to point to the correct gh-pages directory 88 | modified_url = f"https://docs.pyansys.com/sitemap/{project}_sitemap.xml" 89 | 90 | sitemap = ET.SubElement(sitemap_index, "sitemap") 91 | loc = ET.SubElement(sitemap, "loc") 92 | loc.text = modified_url 93 | 94 | # Format XML with indentation 95 | rough_string = ET.tostring(sitemap_index, "utf-8") 96 | reparsed = minidom.parseString(rough_string) 97 | pretty_xml = reparsed.toprettyxml(indent=" ") 98 | 99 | # Create the tree and write to XML file 100 | with dest_path.open(mode="w", encoding="utf-8") as file: 101 | file.write(pretty_xml) 102 | 103 | 104 | if __name__ == "__main__": 105 | # Create path 106 | folder_path = Path() / "sitemaps" 107 | folder_path.mkdir(parents=True, exist_ok=True) 108 | 109 | # Get actual valid URLS and corresponding project names 110 | project_names, project_urls = extract_urls_and_headers(LINKS) 111 | 112 | # Generate global sitemap file 113 | file_path = folder_path / "globalsitemap.xml" 114 | generate_sitemap_index(project_names, file_path) 115 | 116 | for ith_url, url in enumerate(project_urls): 117 | file_path = folder_path / (project_names[ith_url] + "_sitemap.xml") 118 | download_file(url, file_path) 119 | -------------------------------------------------------------------------------- /tools/links.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script for automatic replacement of released links. 3 | 4 | Usage is very simple. Just run the script. 5 | 6 | .. code:: python 7 | 8 | python links.py 9 | """ 10 | 11 | from pathlib import Path 12 | import re 13 | 14 | ROOT_DIR = Path(__file__).parent.parent 15 | """Root directory of the project relative to this file.""" 16 | 17 | PYPROJECT_TOML_FILE = ROOT_DIR / "pyproject.toml" 18 | """Path to pyproject.toml file.""" 19 | 20 | DOCS_DIRECTORY = ROOT_DIR / "doc" / "source" 21 | """Path to the documentation source directory""" 22 | 23 | LINKS = { 24 | "ansys-acp-core": None, # Once stable release is out "https://acp.docs.pyansys.com/version/stable", # noqa: E501 25 | "ansys-additive-core": "https://additive.docs.pyansys.com/version/stable", 26 | "ansys-conceptev-core": "https://conceptev.docs.pyansys.com/version/stable", 27 | "ansys-dpf-composites": "https://composites.dpf.docs.pyansys.com/version/stable", # noqa: E501 28 | "ansys-dpf-core": "https://dpf.docs.pyansys.com/version/stable", 29 | "ansys-dpf-post": "https://post.docs.pyansys.com/version/stable", 30 | "ansys-dpf-gate": None, 31 | "ansys-dyna-core": "https://dyna.docs.pyansys.com/version/stable", 32 | "ansys-dynamicreporting-core": "https://dynamicreporting.docs.pyansys.com/version/stable", # noqa: E501 33 | "ansys-edb-core": "https://edb.core.docs.pyansys.com/version/stable", 34 | "ansys-geometry-core": "https://geometry.docs.pyansys.com/version/stable", 35 | "ansys-fluent-core": "https://fluent.docs.pyansys.com/version/stable", 36 | "ansys-hps-client": "https://hps.docs.pyansys.com/version/stable", 37 | "ansys-hps-data-transfer-client": "https://data-transfer.hps.docs.pyansys.com/version/stable", # noqa: E501 38 | "ansys-mapdl-core": "https://mapdl.docs.pyansys.com/version/stable", 39 | "ansys-math-core": "https://math.docs.pyansys.com/version/stable", 40 | "ansys-sound-core": "https://sound.docs.pyansys.com/version/stable", 41 | "ansys-mechanical-core": "https://mechanical.docs.pyansys.com/version/stable", # noqa: E501 42 | "ansys-meshing-prime": "https://prime.docs.pyansys.com/version/stable", 43 | "ansys-modelcenter-workflow": "https://modelcenter.docs.pyansys.com/version/stable", # noqa: E501 44 | "ansys-motorcad-core": "https://motorcad.docs.pyansys.com/version/stable", 45 | "ansys-openapi-common": None, 46 | "ansys-optislang-core": "https://optislang.docs.pyansys.com/version/stable", 47 | "ansys-platform-instancemanagement": "https://pypim.docs.pyansys.com/version/stable", # noqa: E501 48 | "ansys-pyensight-core": "https://ensight.docs.pyansys.com/version/stable", 49 | "ansys-rocky-core": "https://rocky.docs.pyansys.com/version/stable", 50 | "ansys-seascape": "https://seascape.docs.pyansys.com/version/stable", 51 | "ansys-sherlock-core": "https://sherlock.docs.pyansys.com/version/stable", 52 | "ansys-simai-core": "https://simai.docs.pyansys.com/version/stable", 53 | "ansys-speos-core": "https://speos.docs.pyansys.com/version/stable", 54 | "ansys-systemcoupling-core": "https://systemcoupling.docs.pyansys.com/version/stable", # noqa: E501 55 | "ansys-turbogrid-core": "https://turbogrid.docs.pyansys.com/version/stable", 56 | "ansys-workbench-core": "https://workbench.docs.pyansys.com/version/stable", 57 | "pyedb": "https://edb.docs.pyansys.com/version/stable", 58 | "pyaedt": "https://aedt.docs.pyansys.com/version/stable", 59 | "pygranta": "https://grantami.docs.pyansys.com/version/stable", 60 | "pytwin": "https://twin.docs.pyansys.com/version/stable", 61 | # MAPDL - ALL 62 | "ansys-mapdl-reader": "https://reader.docs.pyansys.com/version/stable", 63 | # FLUENT - ALL 64 | "ansys-fluent-visualization": "https://visualization.fluent.docs.pyansys.com/version/stable", # noqa: E501 65 | # TOOLS 66 | "ansys-materials-manager": "https://manager.materials.docs.pyansys.com/version/stable", 67 | "ansys-tools-filetransfer": "https://filetransfer.tools.docs.pyansys.com/version/stable", # noqa: E501 68 | "ansys-tools-local-product-launcher": "https://local-product-launcher.tools.docs.pyansys.com/version/stable", # noqa: E501 69 | "ansys-tools-path": "https://path.tools.docs.pyansys.com/version/stable", 70 | "ansys-tools-protoc-helper": None, 71 | "ansys-tools-visualization-interface": "https://visualization-interface.tools.docs.pyansys.com/version/stable", # noqa: E501 72 | "ansys-units": "https://units.docs.pyansys.com/version/stable", 73 | "pyansys-tools-report": "https://report.tools.docs.pyansys.com/version/stable", # noqa: E501 74 | "pyansys-tools-versioning": "https://versioning.tools.docs.pyansys.com/version/stable", # noqa: E501 75 | "pyansys-tools-variableinterop": "https://variableinterop.docs.pyansys.com/version/stable", # noqa: E501 76 | } 77 | """Dictionary with PyAnsys packages and their multi-version docs site.""" 78 | 79 | 80 | def retrieve_major_minor(package: str): 81 | """Extract the major and minor version of a pinned package. 82 | 83 | Notes 84 | ----- 85 | This function navigates to the package's pyproject.toml file 86 | 87 | and processes it to retrieve the desired major, minor version. 88 | 89 | 90 | Parameters 91 | ---------- 92 | package : str 93 | The package to be searched for. 94 | 95 | 96 | Returns 97 | ------- 98 | tuple of (int, int) 99 | The major and minor versions of the package. 100 | 101 | """ 102 | with PYPROJECT_TOML_FILE.open("r") as file: 103 | content = file.read() 104 | pattern = r"\b" + re.escape(package) + r"==(\d+)\.(\d+)" 105 | match = re.search(pattern, content) 106 | 107 | if match: 108 | major_version = int(match.group(1)) 109 | minor_version = int(match.group(2)) 110 | return (major_version, minor_version) 111 | 112 | return (None, None) 113 | 114 | 115 | def search_and_replace(link: str, new_link: str): 116 | """Replace existing link with the newly provided link. 117 | 118 | Parameters 119 | ---------- 120 | link : str 121 | The link to be searched for. 122 | new_link : str 123 | The link to replace the existing one. 124 | """ 125 | # Traverse the docs directory 126 | for root, _, files in DOCS_DIRECTORY.walk(): 127 | # Skip the _static subdirectory 128 | if "_static" in root.parts: 129 | continue 130 | 131 | # Process the files 132 | for file in files: 133 | file_path = root / file 134 | content = file_path.read_text(encoding="utf-8") 135 | 136 | # Search for the link in the content, replace and save 137 | if link in content: 138 | new_content = content.replace(link, new_link) 139 | file_path.write_text(new_content, "utf-8") 140 | 141 | print(f"Replaced '{link}' with '{new_link}' in file: {file_path}") # noqa: E501 142 | 143 | 144 | def released_docs(): 145 | """Update links for released documentation. 146 | 147 | Notes 148 | ----- 149 | Links are expected to point to a certain version when released 150 | inside the metapackage, and not to the latest stable version. This 151 | module takes care of updating the links automatically. The script has to 152 | be run locally and the changes have to be committed to the release branch 153 | prior to releasing. 154 | """ 155 | # Loop over all the above defined packages 156 | for key, value in LINKS.items(): 157 | # Packages that are not adapted to multi-version have a None 158 | # link associated as its value... skip them. 159 | if value is None: 160 | continue 161 | 162 | # Retrieve the major and minor versions of the package 163 | major, minor = retrieve_major_minor(key) 164 | 165 | if major is None and minor is None: 166 | # No match found for the link... throw message 167 | print(f"Error retrieving minor/major version of {key}... Skipping.") # noqa: E501 168 | continue 169 | 170 | # Define the new link 171 | link_root = value.split("/version/")[0] 172 | new_link = f"{link_root}/version/{major}.{minor}" 173 | 174 | # Search and replace through all our docs links 175 | search_and_replace(value, new_link) 176 | 177 | 178 | if __name__ == "__main__": 179 | released_docs() 180 | -------------------------------------------------------------------------------- /tools/milestone.py: -------------------------------------------------------------------------------- 1 | """Script for automatically creating a milestone in repositories. 2 | 3 | Only specified repositories (via environment variable) will be handled. 4 | 5 | The purpose of this code is to connect to a specific repository 6 | and create a milestone. This milestone will be associated to a certain date 7 | provided as an input argument. 8 | 9 | """ 10 | 11 | import datetime 12 | import os 13 | 14 | import github 15 | 16 | # Insert your credentials... It should be a PAT. None by default 17 | TOKEN = None 18 | 19 | # Provide the repository you want to create a milestone in... None by default 20 | REPOSITORY = None 21 | 22 | # Provide the release date to be considered... None by default 23 | # If you provide manual input it should be using: 24 | # 25 | # RELEASE_DATE = datetime.datetime.strptime(date_str,"%Y/%m/%d") 26 | # 27 | # where "date_str" must be a string date of format YYYY/MM/DD 28 | RELEASE_DATE = None 29 | 30 | # ============================================================================= 31 | # MODIFY WITH CAUTION FROM THIS POINT ONWARDS 32 | # ============================================================================= 33 | 34 | # Check if a value for TOKEN was provided 35 | if TOKEN is None: 36 | # This probably means that we are creating the milestone automatically 37 | # using our GitHub action: Create milestones for Ansys Release... 38 | # Thus, let us read the GitHub Token or PAT. 39 | print("Reading access token from 'TOKEN' environment variable...") 40 | TOKEN = os.environ.get("TOKEN", default=None) 41 | 42 | # Check if a value for REPOSITORY was provided 43 | if REPOSITORY is None: 44 | # This probably means that we are creating the milestone automatically 45 | # using our GitHub action: Create milestones for Ansys Release... 46 | # Thus, let us read the repository name. 47 | print("Reading target repo from 'REPOSITORY' environment variable...") 48 | REPOSITORY = os.environ.get("REPOSITORY", default=None) 49 | 50 | # Check if a value for RELEASE_DATE was provided 51 | if RELEASE_DATE is None: 52 | # This probably means that we are creating the milestone automatically 53 | # using our GitHub action: Create milestones for Ansys Release... 54 | # Thus, let us read the release date to be considered. 55 | print("Reading target repo from 'RELEASE_DATE' environment variable...") 56 | env_var = os.environ.get("RELEASE_DATE", default=None) 57 | if env_var is not None: 58 | try: 59 | RELEASE_DATE = datetime.datetime.strptime(env_var, "%Y/%m/%d") 60 | except (TypeError, ValueError, IndexError, KeyError): 61 | raise RuntimeError( 62 | """Problem parsing input date. It should be a string in format YYYY/MM/DD""" # noqa: E501 63 | ) 64 | 65 | 66 | # If the value for TOKEN, REPOSITORY, RELEASE_DATE is None... throw error! 67 | if TOKEN is None: 68 | raise ValueError("No TOKEN value available. Consider adding it.") 69 | elif REPOSITORY is None: 70 | raise ValueError("No REPOSITORY value available. Consider adding it.") 71 | elif RELEASE_DATE is None: 72 | raise ValueError("No RELEASE_DATE value available. Consider adding it.") 73 | 74 | # Create a connection to GitHub 75 | g = github.Github(TOKEN) 76 | 77 | # Get the repository we want to create the milestone at 78 | repo = g.get_repo(REPOSITORY) 79 | 80 | # Get its last release - assuming semantic versioning (i.e. v0.1.0) 81 | major, minor, *_ = repo.get_latest_release().tag_name.replace("v", "").split(".") # noqa: E501 82 | next_release = f"v{major}.{int(minor) + 1}.0" 83 | 84 | # Get its available milestones 85 | milestones = repo.get_milestones(state="all") 86 | 87 | # Check if there is already any milestone whose name matches "next_release" 88 | is_created = False 89 | for milestone in milestones: 90 | if next_release in milestone.title: 91 | # The release is already created! 92 | is_created = True 93 | break 94 | 95 | # If the milestone hasn't been created yet... go ahead! 96 | if not is_created: 97 | # Milestone information 98 | desc = f"""This repository is part of an Ansys Release (unified install). 99 | 100 | Thus, it is necessary to create a release for the next Ansys release that is compatible with it. Please consider releasing by {RELEASE_DATE.strftime("%Y/%m/%d")}. 101 | 102 | If your current release is the one expected to be used in the upcoming official Ansys Release, please close and delete this milestone.""" # noqa: E501 103 | 104 | # Create a new milestone 105 | repo.create_milestone( 106 | title=next_release, 107 | state="open", 108 | description=desc, 109 | due_on=RELEASE_DATE + datetime.timedelta(hours=12), 110 | ) 111 | 112 | print(f"Milestone was created at {REPOSITORY} with name {next_release}!") 113 | else: 114 | print(f"Milestone was already available at {REPOSITORY}... Skipping creation!") # noqa: 501 115 | --------------------------------------------------------------------------------