From 775fa86f09f2b82b1a2871475eef53d2e752f2b2 Mon Sep 17 00:00:00 2001 From: Mainak Kundu <94432368+mkundu1@users.noreply.github.com> Date: Sun, 28 Aug 2022 23:33:18 +0530 Subject: [PATCH] Segregate generated files into Fluent-version-specific directories (#771) * Segregate generated files into Fluent-version-specific directories --- .github/workflows/ci.yml | 182 ++++++------------ .gitignore | 15 +- .pre-commit-config.yaml | 13 +- codegen/datamodelgen.py | 26 ++- codegen/print_fluent_version.py | 16 +- codegen/settingsgen.py | 6 +- codegen/tuigen.py | 149 +++++++------- doc/settings_rstgen.py | 24 ++- src/ansys/fluent/core/fluent_connection.py | 4 + src/ansys/fluent/core/session.py | 24 ++- src/ansys/fluent/core/session_base_meshing.py | 49 +++-- src/ansys/fluent/core/session_solver.py | 23 ++- src/ansys/fluent/core/solver/flobject.py | 7 +- src/ansys/fluent/core/utils/fluent_version.py | 21 ++ 14 files changed, 287 insertions(+), 272 deletions(-) create mode 100644 src/ansys/fluent/core/utils/fluent_version.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 382898e9067..e02451288bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,11 +157,11 @@ jobs: id: cache-api-code with: path: | - src/ansys/fluent/core/datamodel - src/ansys/fluent/core/fluent_version.py - src/ansys/fluent/core/meshing/tui.py - src/ansys/fluent/core/solver/settings - src/ansys/fluent/core/solver/tui.py + src/ansys/fluent/core/datamodel_222 + src/ansys/fluent/core/fluent_version_222.py + src/ansys/fluent/core/meshing/tui_222.py + src/ansys/fluent/core/solver/settings_222 + src/ansys/fluent/core/solver/tui_222.py doc/source/api/core/meshing/tui doc/source/api/core/meshing/datamodel doc/source/api/core/solver/tui @@ -230,14 +230,10 @@ jobs: FOLDER: doc/_build/html CLEAN: true - test: + build-test: name: Unit Testing needs: test-import runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - image-tag: [v22.2.0, v23.1.0] steps: - uses: actions/checkout@v3 @@ -267,165 +263,103 @@ jobs: echo "PYFLUENT version is: $(python -c "from ansys.fluent.core import __version__; print(__version__)")" id: version - - name: Cache API Code + - name: Cache 22.2 API Code uses: actions/cache@v3 - id: cache-api-code + id: cache-222-api-code with: path: - src/ansys/fluent/core/datamodel - src/ansys/fluent/core/fluent_version.py - src/ansys/fluent/core/meshing/tui.py - src/ansys/fluent/core/solver/settings - src/ansys/fluent/core/solver/tui.py + src/ansys/fluent/core/datamodel_222 + src/ansys/fluent/core/fluent_version_222.py + src/ansys/fluent/core/meshing/tui_222.py + src/ansys/fluent/core/solver/settings_222 + src/ansys/fluent/core/solver/tui_222.py doc/source/api/core/meshing/tui doc/source/api/core/meshing/datamodel doc/source/api/core/solver/tui doc/source/api/core/solver/datamodel - key: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-${{ matrix.image-tag }}-${{ hashFiles('codegen/**') }} - restore-keys: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-${{ matrix.image-tag }} + key: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-v22.2.0-${{ hashFiles('codegen/**') }} + restore-keys: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-v22.2.0 - name: Login to GitHub Container Registry - if: steps.cache-api-code.outputs.cache-hit != 'true' uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ secrets.GH_USERNAME }} password: ${{ secrets.REPO_DOWNLOAD_PAT }} - - name: Pull Fluent docker image - if: steps.cache-api-code.outputs.cache-hit != 'true' + - name: Pull 22.2 Fluent docker image + if: steps.cache-222-api-code.outputs.cache-hit != 'true' run: make docker-pull env: - FLUENT_IMAGE_TAG: ${{ matrix.image-tag }} + FLUENT_IMAGE_TAG: v22.2.0 - - name: Run API codegen - if: steps.cache-api-code.outputs.cache-hit != 'true' + - name: Run 22.2 API codegen + if: steps.cache-222-api-code.outputs.cache-hit != 'true' run: make api-codegen env: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} PYFLUENT_START_INSTANCE: 0 PYFLUENT_LAUNCH_CONTAINER: 1 - FLUENT_IMAGE_TAG: ${{ matrix.image-tag }} - - - name: Install again after codegen - run: | - rm -rf dist - make install > /dev/null - - - name: Unit Testing - run: make unittest - env: - ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} - PYFLUENT_START_INSTANCE: 0 - FLUENT_IMAGE_TAG: ${{ matrix.image-tag }} - - - name: Upload Coverage Results - if: matrix.image-tag == 'v22.2.0' - uses: actions/upload-artifact@v3 - with: - name: HTML-Coverage-tag-${{ matrix.image-tag }} - path: cov_html - retention-days: 7 - - - name: Check package - if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/v') - run: | - pip install twine - twine check dist/* - - - name: Upload package - if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/v') - uses: actions/upload-artifact@v3 - with: - name: PyFluent-packages - path: | - dist/*.whl - dist/*.tar.gz - retention-days: 7 - - build: - name: Build for release - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') - needs: test-import - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - image-tag: [v22.2.0] - - steps: - - uses: actions/checkout@v3 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: 3.9 + FLUENT_IMAGE_TAG: v22.2.0 - - name: Cache pip + - name: Cache 23.1 API Code uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: Python-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('setup.py') }}-${{ hashFiles('requirements/requirements_*.txt') }} - restore-keys: | - Python-${{ runner.os }}-${{ matrix.python-version }} - - - name: Add version information - run: make version-info - - - name: Install pyfluent - run: make install - - - name: Retrieve PyFluent version - run: | - echo "::set-output name=PYFLUENT_VERSION::$(python -c "from ansys.fluent.core import __version__; print(__version__)")" - echo "PYFLUENT version is: $(python -c "from ansys.fluent.core import __version__; print(__version__)")" - id: version - - - name: Cache API Code - uses: actions/cache@v3 - id: cache-api-code + id: cache-231-api-code with: path: - src/ansys/fluent/core/datamodel - src/ansys/fluent/core/fluent_version.py - src/ansys/fluent/core/meshing/tui.py - src/ansys/fluent/core/solver/settings - src/ansys/fluent/core/solver/tui.py + src/ansys/fluent/core/datamodel_231 + src/ansys/fluent/core/fluent_version_231.py + src/ansys/fluent/core/meshing/tui_231.py + src/ansys/fluent/core/solver/settings_231 + src/ansys/fluent/core/solver/tui_231.py doc/source/api/core/meshing/tui doc/source/api/core/meshing/datamodel doc/source/api/core/solver/tui doc/source/api/core/solver/datamodel - key: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-${{ matrix.image-tag }}-${{ hashFiles('codegen/**') }} - restore-keys: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-${{ matrix.image-tag }} - - - name: Login to GitHub Container Registry - if: steps.cache-api-code.outputs.cache-hit != 'true' - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ secrets.GH_USERNAME }} - password: ${{ secrets.REPO_DOWNLOAD_PAT }} + key: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-v23.1.0-${{ hashFiles('codegen/**') }} + restore-keys: API-Code-v${{ env.API_CODE_CACHE }}-${{ steps.version.outputs.PYFLUENT_VERSION }}-v23.1.0 - - name: Pull Fluent docker image - if: steps.cache-api-code.outputs.cache-hit != 'true' + - name: Pull 23.1 Fluent docker image + if: steps.cache-231-api-code.outputs.cache-hit != 'true' run: make docker-pull env: - FLUENT_IMAGE_TAG: ${{ matrix.image-tag }} + FLUENT_IMAGE_TAG: v23.1.0 - - name: Run API codegen - if: steps.cache-api-code.outputs.cache-hit != 'true' + - name: Run 23.1 API codegen + if: steps.cache-231-api-code.outputs.cache-hit != 'true' run: make api-codegen env: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} PYFLUENT_START_INSTANCE: 0 PYFLUENT_LAUNCH_CONTAINER: 1 - FLUENT_IMAGE_TAG: ${{ matrix.image-tag }} + FLUENT_IMAGE_TAG: v23.1.0 - name: Install again after codegen run: | rm -rf dist make install > /dev/null + - name: 22.2 Unit Testing + run: make unittest + env: + ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} + PYFLUENT_START_INSTANCE: 0 + FLUENT_IMAGE_TAG: v22.2.0 + + - name: Upload Coverage Results + uses: actions/upload-artifact@v3 + with: + name: HTML-Coverage-tag-222 + path: cov_html + retention-days: 7 + + - name: 23.1 Unit Testing + run: make unittest + env: + ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} + PYFLUENT_START_INSTANCE: 0 + FLUENT_IMAGE_TAG: v23.1.0 + - name: Check package run: | pip install twine @@ -443,7 +377,7 @@ jobs: release: name: Release if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') - needs: [test, build] + needs: build-test runs-on: ubuntu-latest steps: - name: Set up Python diff --git a/.gitignore b/.gitignore index ebfe08fd477..ac8653ce687 100644 --- a/.gitignore +++ b/.gitignore @@ -135,8 +135,13 @@ dmypy.json .vscode # generated API files -src/ansys/fluent/core/fluent_version.py -src/ansys/fluent/core/meshing/tui.py -src/ansys/fluent/core/solver/tui.py -src/ansys/fluent/core/datamodel/ -src/ansys/fluent/core/solver/settings/ +src/ansys/fluent/core/fluent_version_222.py +src/ansys/fluent/core/meshing/tui_222.py +src/ansys/fluent/core/solver/tui_222.py +src/ansys/fluent/core/datamodel_222/ +src/ansys/fluent/core/solver/settings_222/ +src/ansys/fluent/core/fluent_version_231.py +src/ansys/fluent/core/meshing/tui_231.py +src/ansys/fluent/core/solver/tui_231.py +src/ansys/fluent/core/datamodel_222/ +src/ansys/fluent/core/solver/settings_222/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8d47d9ae6ec..a9ff0968385 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: hooks: - id: black args: [ - --force-exclude, src/ansys/api/fluent/v0/|src/ansys/fluent/core/meshing/tui.py|src/ansys/fluent/core/solver/tui.py|src/ansys/fluent/core/solver/settings/|src/ansys/fluent/core/datamodel, + --force-exclude, src/ansys/fluent/core/meshing/tui|src/ansys/fluent/core/solver/tui|src/ansys/fluent/core/solver/settings/|src/ansys/fluent/core/datamodel, src/ansys, codegen, doc, examples, tests ] @@ -22,9 +22,8 @@ repos: - id: isort args: [ --profile, black, - --skip, src/ansys/fluent/core/meshing/tui.py, - --skip, src/ansys/fluent/core/solver/tui.py, - --skip-glob, src/ansys/api/fluent/v0/*, + --skip-glob, src/ansys/fluent/core/meshing/tui*, + --skip-glob, src/ansys/fluent/core/solver/tui*, --skip-glob, src/ansys/fluent/core/datamodel/*, --skip-glob, src/ansys/fluent/core/solver/settings/*, --force-sort-within-sections, @@ -43,7 +42,7 @@ repos: 'flake8-annotations==2.9.0' ] args: [ - --exclude, src/ansys/api/fluent/v0/* src/ansys/fluent/core/meshing/tui.py src/ansys/fluent/core/solver/tui.py src/ansys/fluent/core/datamodel/* src/ansys/fluent/core/solver/settings/*, + --exclude, src/ansys/fluent/core/meshing/tui* src/ansys/fluent/core/solver/tui* src/ansys/fluent/core/datamodel/* src/ansys/fluent/core/solver/settings/*, --select, W191 W291 W293 W391 E115 E117 E122 E124 E125 E225 E231 E301 E303 F401 F403 N801 N802 N803 N804 N805 N806, #--select, W191 W291 W293 W391 E115 E117 E122 E124 E125 E225 E231 E301 E303 F401 F403 N801 N802 N803 N804 N805 N806 ANN001 ANN201 ANN205 ANN206, --count, @@ -59,14 +58,14 @@ repos: hooks: - id: codespell args: [ - --skip, "src/ansys/api/fluent/v0/*,src/ansys/fluent/core/meshing/tui.py,src/ansys/fluent/core/solver/tui.py,src/ansys/fluent/core/datamodel/*,codegen/data/fluent_gui_help.xml,src/ansys/fluent/core/solver/settings/*", + --skip, "src/ansys/fluent/core/meshing/tui*,src/ansys/fluent/core/solver/tui*,src/ansys/fluent/core/datamodel/*,codegen/data/fluent_gui_help.xml,src/ansys/fluent/core/solver/settings/*", ] - repo: https://github.com/myint/docformatter rev: v1.3.1 hooks: - id: docformatter - exclude: ^(tests\/|src\/ansys\/api\/fluent\/v0\/|src\/ansys\/fluent\/core\/meshing\/tui.py|src\/ansys\/fluent\/core\/solver\/tui.py|src\/ansys\/fluent\/core\/solver\/settings\/|src\/ansys\/fluent\/core\/datamodel\/) + exclude: ^(tests\/|src\/ansys\/fluent\/core\/meshing\/tui_222.py|src\/ansys\/fluent\/core\/solver\/tui_222.py|src\/ansys\/fluent\/core\/solver\/settings_222\/|src\/ansys\/fluent\/core\/datamodel_222\/|src\/ansys\/fluent\/core\/meshing\/tui_231.py|src\/ansys\/fluent\/core\/solver\/tui_231.py|src\/ansys\/fluent\/core\/solver\/settings_231\/|src\/ansys\/fluent\/core\/datamodel_231\/) args: [-r, --in-place] #- repo: https://github.com/pycqa/pydocstyle diff --git a/codegen/datamodelgen.py b/codegen/datamodelgen.py index 3d749f0c9d9..a5369d4f475 100644 --- a/codegen/datamodelgen.py +++ b/codegen/datamodelgen.py @@ -6,6 +6,7 @@ from ansys.api.fluent.v0 import datamodel_se_pb2 as DataModelProtoModule from ansys.fluent.core.session import _BaseSession as Session +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath _THIS_DIR = Path(__file__).parent @@ -81,12 +82,18 @@ def _build_command_docstring(name: str, info: Any, indent: str): class DataModelStaticInfo: - def __init__(self, rules: str, mode: str): + def __init__(self, rules: str, mode: str, version: str): self.rules = rules self.mode = mode self.static_info = None datamodel_dir = ( - _THIS_DIR / ".." / "src" / "ansys" / "fluent" / "core" / "datamodel" + _THIS_DIR + / ".." + / "src" + / "ansys" + / "fluent" + / "core" + / f"datamodel_{version}" ) datamodel_dir.mkdir(exist_ok=True) self.filepath = (datamodel_dir / f"{rules}.py").resolve() @@ -94,11 +101,16 @@ def __init__(self, rules: str, mode: str): class DataModelGenerator: def __init__(self): + self.version = get_version_for_filepath() self._static_info: Dict[str, DataModelStaticInfo] = { - "workflow": DataModelStaticInfo("workflow", "meshing"), - "meshing": DataModelStaticInfo("meshing", "meshing"), - "PartManagement": DataModelStaticInfo("PartManagement", "meshing"), - "PMFileManagement": DataModelStaticInfo("PMFileManagement", "meshing"), + "workflow": DataModelStaticInfo("workflow", "meshing", self.version), + "meshing": DataModelStaticInfo("meshing", "meshing", self.version), + "PartManagement": DataModelStaticInfo( + "PartManagement", "meshing", self.version + ), + "PMFileManagement": DataModelStaticInfo( + "PMFileManagement", "meshing", self.version + ), } self._delete_generated_files() self._populate_static_info() @@ -301,7 +313,7 @@ def write_static_info(self) -> None: info.static_info, doc_dir / name, f"{info.mode}.datamodel.{name}", - f"ansys.fluent.core.datamodel.{name}", + f"ansys.fluent.core.datamodel_{self.version}.{name}", "Root", ) diff --git a/codegen/print_fluent_version.py b/codegen/print_fluent_version.py index 67dc67057fc..31d3d305db4 100644 --- a/codegen/print_fluent_version.py +++ b/codegen/print_fluent_version.py @@ -1,17 +1,25 @@ import os import ansys.fluent.core as pyfluent +from ansys.fluent.core.utils.fluent_version import get_version, get_version_for_filepath _THIS_DIR = os.path.dirname(__file__) -_VERSION_FILE = os.path.join( - _THIS_DIR, "..", "src", "ansys", "fluent", "core", "fluent_version.py" -) def print_fluent_version(): session = pyfluent.launch_fluent(mode="solver") eval = session.scheme_eval.scheme_eval - with open(_VERSION_FILE, "w", encoding="utf8") as f: + version_file = os.path.join( + _THIS_DIR, + "..", + "src", + "ansys", + "fluent", + "core", + f"fluent_version_{get_version_for_filepath()}.py", + ) + with open(version_file, "w", encoding="utf8") as f: + f.write(f'FLUENT_VERSION = "{get_version()}"\n') f.write(f'FLUENT_BUILD_TIME = "{eval("(inquire-build-time)")}"\n') f.write(f'FLUENT_BUILD_ID = "{eval("(inquire-build-id)")}"\n') f.write(f'FLUENT_REVISION = "{eval("(inquire-src-vcs-id)")}"\n') diff --git a/codegen/settingsgen.py b/codegen/settingsgen.py index 314474d9de2..a341683d035 100644 --- a/codegen/settingsgen.py +++ b/codegen/settingsgen.py @@ -32,6 +32,7 @@ import shutil from ansys.fluent.core.solver import flobject +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath hash_dict = {} files_dict = {} @@ -300,6 +301,8 @@ def _populate_init(parent_dir, sinfo): def generate(): from ansys.fluent.core.launcher.launcher import launch_fluent + session = launch_fluent(mode="solver") + version = get_version_for_filepath(session=session) dirname = os.path.dirname(__file__) parent_dir = os.path.normpath( os.path.join( @@ -310,7 +313,7 @@ def generate(): "fluent", "core", "solver", - "settings", + f"settings_{version}", ) ) @@ -319,7 +322,6 @@ def generate(): shutil.rmtree(parent_dir) os.makedirs(parent_dir) - session = launch_fluent(mode="solver") sinfo = session._settings_service.get_static_info() session.exit() cls = flobject.get_cls("", sinfo) diff --git a/codegen/tuigen.py b/codegen/tuigen.py index 4d212a1f497..1109ac29588 100644 --- a/codegen/tuigen.py +++ b/codegen/tuigen.py @@ -20,6 +20,7 @@ import string import subprocess from typing import Any, Dict +import uuid import xml.etree.ElementTree as ET from data.fluent_gui_help_patch import XML_HELP_PATCH @@ -27,86 +28,71 @@ import ansys.fluent.core as pyfluent from ansys.fluent.core import LOG -from ansys.fluent.core.launcher.launcher import FLUENT_VERSION, get_fluent_path +from ansys.fluent.core.launcher.launcher import get_fluent_path from ansys.fluent.core.services.datamodel_tui import ( PyMenu, convert_path_to_grpc_path, convert_tui_menu_to_func_name, ) +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath _THIS_DIRNAME = os.path.dirname(__file__) -_MESHING_TUI_FILE = os.path.normpath( - os.path.join( - _THIS_DIRNAME, - "..", - "src", - "ansys", - "fluent", - "core", - "meshing", - "tui.py", - ) -) -_SOLVER_TUI_FILE = os.path.normpath( - os.path.join( - _THIS_DIRNAME, - "..", - "src", - "ansys", - "fluent", - "core", - "solver", - "tui.py", + + +def _get_tui_filepath(mode: str, version: str): + return os.path.normpath( + os.path.join( + _THIS_DIRNAME, + "..", + "src", + "ansys", + "fluent", + "core", + mode, + f"tui_{version}.py", + ) ) -) + + _INDENT_STEP = 4 -_MESHING_TUI_DOC_DIR = os.path.normpath( - os.path.join( - _THIS_DIRNAME, - "..", - "doc", - "source", - "api", - "core", - "meshing", - "tui", - ) -) -_SOLVER_TUI_DOC_DIR = os.path.normpath( - os.path.join( - _THIS_DIRNAME, - "..", - "doc", - "source", - "api", - "core", - "solver", - "tui", + +def _get_tui_docdir(mode: str): + return os.path.normpath( + os.path.join( + _THIS_DIRNAME, + "..", + "doc", + "source", + "api", + "core", + mode, + f"tui", + ) ) -) + _XML_HELP_FILE = os.path.normpath( os.path.join(_THIS_DIRNAME, "data", "fluent_gui_help.xml") ) _XML_HELPSTRINGS = {} -_FLUENT_IMAGE_TAG = os.getenv("FLUENT_IMAGE_TAG", "latest") -_FLUENT_IMAGE_NAME = f"ghcr.io/pyansys/pyfluent:{_FLUENT_IMAGE_TAG}" - -def _copy_tui_help_xml_file(): +def _copy_tui_help_xml_file(version: str): if os.getenv("PYFLUENT_LAUNCH_CONTAINER") == "1": - import docker - - client = docker.from_env() - container = client.containers.create(_FLUENT_IMAGE_NAME) - xml_source = f"/ansys_inc/v{FLUENT_VERSION[0].replace('.', '')}/commonfiles/help/en-us/fluent_gui_help/fluent_gui_help.xml" + image_tag = os.getenv("FLUENT_IMAGE_TAG", "v23.1.0") + image_name = f"ghcr.io/pyansys/pyfluent:{image_tag}" + container_name = uuid.uuid4().hex is_linux = platform.system() == "Linux" subprocess.run( - f"docker cp {container.name}:{xml_source} {_XML_HELP_FILE}", shell=is_linux + f"docker container create --name {container_name} {image_name}", + shell=is_linux, ) - container.remove() + xml_source = f"/ansys_inc/v{version}/commonfiles/help/en-us/fluent_gui_help/fluent_gui_help.xml" + subprocess.run( + f"docker cp {container_name}:{xml_source} {_XML_HELP_FILE}", shell=is_linux + ) + subprocess.run(f"docker container rm {container_name}", shell=is_linux) else: xml_source = ( @@ -180,23 +166,18 @@ def get_command_path(self, command: str) -> str: class TUIGenerator: """Class to generate explicit TUI menu classes.""" - def __init__( - self, - meshing_tui_file: str = _MESHING_TUI_FILE, - solver_tui_file: str = _SOLVER_TUI_FILE, - meshing_tui_doc_dir: str = _MESHING_TUI_DOC_DIR, - solver_tui_doc_dir: str = _SOLVER_TUI_DOC_DIR, - meshing: bool = False, - ): - self._tui_file = meshing_tui_file if meshing else solver_tui_file + def __init__(self, mode: str, version: str): + self._mode = mode + self._version = version + self._tui_file = _get_tui_filepath(mode, version) if Path(self._tui_file).exists(): Path(self._tui_file).unlink() - self._tui_doc_dir = meshing_tui_doc_dir if meshing else solver_tui_doc_dir - self._tui_heading = ("meshing" if meshing else "solver") + ".tui" - self._tui_module = "ansys.fluent.core." + self._tui_heading + self._tui_doc_dir = _get_tui_docdir(mode) + self._tui_heading = mode + ".tui" + self._tui_module = "ansys.fluent.core." + self._tui_heading + f"_{version}" if Path(self._tui_doc_dir).exists(): shutil.rmtree(Path(self._tui_doc_dir)) - self.session = pyfluent.launch_fluent(mode="meshing" if meshing else "solver") + self.session = pyfluent.launch_fluent(mode=mode) self._service = self.session.fluent_connection.datamodel_service_tui self._main_menu = _TUIMenu([], "") @@ -311,11 +292,12 @@ def _write_doc_for_menu(self, menu, doc_dir: Path, heading, class_name) -> None: def generate(self) -> None: Path(self._tui_file).parent.mkdir(exist_ok=True) with open(self._tui_file, "w", encoding="utf8") as self.__writer: - mode = "meshing" if self._tui_file == _MESHING_TUI_FILE else "solver" - if self.session.get_fluent_version() == "22.2.0": + if self._version == "222": with open( os.path.join( - _THIS_DIRNAME, "data", f"static_info_222_{mode}.pickle" + _THIS_DIRNAME, + "data", + f"static_info_{self._version}_{self._mode}.pickle", ), "rb", ) as f: @@ -324,12 +306,10 @@ def generate(self) -> None: info = PyMenu(self._service, self._main_menu.path).get_static_info() self._populate_menu(self._main_menu, info) self.session.exit() - if mode == "meshing": - self._write_code_to_tui_file('"""Fluent Meshing TUI Commands"""\n') - self._main_menu.doc = "Fluent meshing main menu." - else: - self._write_code_to_tui_file('"""Fluent Solver TUI Commands"""\n') - self._main_menu.doc = "Fluent solver main menu." + self._write_code_to_tui_file( + f'"""Fluent {self._mode.title()} TUI Commands"""\n' + ) + self._main_menu.doc = f"Fluent {self._mode} main menu." self._write_code_to_tui_file( "#\n" "# This is an auto-generated file. DO NOT EDIT!\n" @@ -350,11 +330,12 @@ def generate(self) -> None: def generate(): # pyfluent.set_log_level("WARNING") - if FLUENT_VERSION[0] > "22.2": - _copy_tui_help_xml_file() + version = get_version_for_filepath() + if version > "222": + _copy_tui_help_xml_file(version) _populate_xml_helpstrings() - TUIGenerator(meshing=True).generate() - TUIGenerator(meshing=False).generate() + TUIGenerator("meshing", version).generate() + TUIGenerator("solver", version).generate() LOG.warning( "XML help is available but not picked for the following %i paths:", len(_XML_HELPSTRINGS), diff --git a/doc/settings_rstgen.py b/doc/settings_rstgen.py index 5488bfcfdf7..44b839d40e4 100644 --- a/doc/settings_rstgen.py +++ b/doc/settings_rstgen.py @@ -23,9 +23,10 @@ python """ +import importlib import os -from ansys.fluent.core.solver import settings +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath parents_dict = {} rst_list = [] @@ -109,7 +110,7 @@ def _populate_parents_list(cls): _populate_parents_list(getattr(cls, "child_object_type")) -def _populate_rst_from_settings(rst_dir, cls): +def _populate_rst_from_settings(rst_dir, cls, version): istr1 = _get_indent_str(1) cls_name = cls.__name__ file_name = cls.__module__.split(".")[-1] @@ -124,7 +125,9 @@ def _populate_rst_from_settings(rst_dir, cls): r.write(f".. _{file_name}:\n\n") r.write(f"{cls_name}\n") r.write(f'{"="*(len(cls_name))}\n\n') - r.write(f".. currentmodule:: ansys.fluent.core.solver.settings.{file_name}\n\n") + r.write( + f".. currentmodule:: ansys.fluent.core.solver.settings_{version}.{file_name}\n\n" + ) r.write(f".. autoclass:: {cls_name}\n") r.write(f"{istr1}:show-inheritance:\n") r.write(f"{istr1}:undoc-members:\n") @@ -183,18 +186,20 @@ def _populate_rst_from_settings(rst_dir, cls): rst_list.append(rstpath) if has_children: for child in cls.child_names: - _populate_rst_from_settings(rst_dir, getattr(cls, child)) + _populate_rst_from_settings(rst_dir, getattr(cls, child), version) if has_commands: for child in cls.command_names: - _populate_rst_from_settings(rst_dir, getattr(cls, child)) + _populate_rst_from_settings(rst_dir, getattr(cls, child), version) if has_arguments: for child in cls.argument_names: - _populate_rst_from_settings(rst_dir, getattr(cls, child)) + _populate_rst_from_settings(rst_dir, getattr(cls, child), version) if has_named_object: - _populate_rst_from_settings(rst_dir, getattr(cls, "child_object_type")) + _populate_rst_from_settings( + rst_dir, getattr(cls, "child_object_type"), version + ) if __name__ == "__main__": @@ -214,5 +219,8 @@ def _populate_rst_from_settings(rst_dir, cls): if not os.path.exists(rst_dir): os.makedirs(rst_dir) + image_tag = os.getenv("FLUENT_IMAGE_TAG", "v22.2.0") + version = get_version_for_filepath(image_tag.lstrip("v")) + settings = importlib.import_module(f"ansys.fluent.core.solver.settings_{version}") _populate_parents_list(settings.root) - _populate_rst_from_settings(rst_dir, settings.root) + _populate_rst_from_settings(rst_dir, settings.root, version) diff --git a/src/ansys/fluent/core/fluent_connection.py b/src/ansys/fluent/core/fluent_connection.py index f2ff1ba8a9e..6170dadbc19 100644 --- a/src/ansys/fluent/core/fluent_connection.py +++ b/src/ansys/fluent/core/fluent_connection.py @@ -248,6 +248,10 @@ def check_health(self) -> str: else: return HealthCheckService.Status.NOT_SERVING.name + def get_fluent_version(self): + """Gets and returns the fluent version.""" + return ".".join(map(str, self.scheme_eval.scheme_eval("(cx-version)"))) + def exit(self) -> None: """Close the Fluent connection and exit Fluent.""" self._finalizer() diff --git a/src/ansys/fluent/core/session.py b/src/ansys/fluent/core/session.py index d163763b4db..466c8ee4f9c 100644 --- a/src/ansys/fluent/core/session.py +++ b/src/ansys/fluent/core/session.py @@ -1,5 +1,6 @@ """Module containing class encapsulating Fluent connection and the Base Session.""" +import importlib import json from typing import Any import warnings @@ -15,6 +16,7 @@ from ansys.fluent.core.session_base_meshing import _BaseMeshing from ansys.fluent.core.session_shared import _CODEGEN_MSG_TUI from ansys.fluent.core.solver.flobject import get_root as settings_get_root +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath from ansys.fluent.core.utils.logging import LOG try: @@ -147,9 +149,7 @@ def stop_journal(self, port_data=None): def get_fluent_version(self): """Gets and returns the fluent version.""" - return ".".join( - map(str, self.fluent_connection.scheme_eval.scheme_eval("(cx-version)")) - ) + return self.fluent_connection.get_fluent_version() def __enter__(self): """Close the Fluent connection and exit Fluent.""" @@ -327,6 +327,13 @@ def __init__( self._settings_service = settings_service self._tui = None self._settings_root = None + self._version = None + + @property + def version(self): + if self._version is None: + self._version = get_version_for_filepath(session=self) + return self._version @property def tui(self): @@ -334,9 +341,10 @@ def tui(self): can be executed.""" if self._tui is None: try: - from ansys.fluent.core.solver.tui import main_menu as SolverMainMenu - - self._tui = SolverMainMenu([], self._tui_service) + tui_module = importlib.import_module( + f"ansys.fluent.core.solver.tui_{self.version}" + ) + self._tui = tui_module.main_menu([], self._tui_service) except (ImportError, ModuleNotFoundError): LOG.warning(_CODEGEN_MSG_TUI) self._tui = TUIMenuGeneric([], self._tui_service) @@ -346,5 +354,7 @@ def tui(self): def root(self): """root settings object.""" if self._settings_root is None: - self._settings_root = settings_get_root(flproxy=self._settings_service) + self._settings_root = settings_get_root( + flproxy=self._settings_service, version=self.version + ) return self._settings_root diff --git a/src/ansys/fluent/core/session_base_meshing.py b/src/ansys/fluent/core/session_base_meshing.py index b8816a0c8ff..55c5e913508 100644 --- a/src/ansys/fluent/core/session_base_meshing.py +++ b/src/ansys/fluent/core/session_base_meshing.py @@ -1,9 +1,12 @@ +import importlib + from ansys.fluent.core.fluent_connection import _FluentConnection from ansys.fluent.core.meshing.meshing import Meshing from ansys.fluent.core.meshing.workflow import MeshingWorkflow from ansys.fluent.core.services.datamodel_se import PyMenuGeneric from ansys.fluent.core.services.datamodel_tui import TUIMenuGeneric from ansys.fluent.core.session_shared import _CODEGEN_MSG_DATAMODEL, _CODEGEN_MSG_TUI +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath from ansys.fluent.core.utils.logging import LOG @@ -21,6 +24,17 @@ def __init__(self, session_execute_tui, fluent_connection: _FluentConnection): self._part_management = None self._pm_file_management = None self._session_execute_tui = session_execute_tui + self._version = None + + def get_fluent_version(self): + """Gets and returns the fluent version.""" + return self._fluent_connection.get_fluent_version() + + @property + def version(self): + if self._version is None: + self._version = get_version_for_filepath(session=self) + return self._version @property def tui(self): @@ -28,9 +42,10 @@ def tui(self): executed.""" if self._tui is None: try: - from ansys.fluent.core.meshing.tui import main_menu as MeshingMainMenu - - self._tui = MeshingMainMenu([], self._tui_service) + tui_module = importlib.import_module( + f"ansys.fluent.core.meshing.tui_{self.version}" + ) + self._tui = tui_module.main_menu([], self._tui_service) except (ImportError, ModuleNotFoundError): LOG.warning(_CODEGEN_MSG_TUI) self._tui = TUIMenuGeneric([], self._tui_service) @@ -40,9 +55,10 @@ def tui(self): def _meshing_root(self): """meshing datamodel root.""" try: - from ansys.fluent.core.datamodel.meshing import Root as meshing_root - - meshing_root = meshing_root(self._se_service, "meshing", []) + meshing_module = importlib.import_module( + f"ansys.fluent.core.datamodel_{self.version}.meshing" + ) + meshing_root = meshing_module.Root(self._se_service, "meshing", []) except (ImportError, ModuleNotFoundError): LOG.warning(_CODEGEN_MSG_DATAMODEL) meshing_root = PyMenuGeneric(self._se_service, "meshing") @@ -63,9 +79,10 @@ def meshing(self): def _workflow_se(self): """workflow datamodel root.""" try: - from ansys.fluent.core.datamodel.workflow import Root as workflow_root - - workflow_se = workflow_root(self._se_service, "workflow", []) + workflow_module = importlib.import_module( + f"ansys.fluent.core.datamodel_{self.version}.workflow" + ) + workflow_se = workflow_module.Root(self._se_service, "workflow", []) except (ImportError, ModuleNotFoundError): LOG.warning(_CODEGEN_MSG_DATAMODEL) workflow_se = PyMenuGeneric(self._se_service, "workflow") @@ -82,11 +99,10 @@ def PartManagement(self): """PartManagement datamodel root.""" if self._part_management is None: try: - from ansys.fluent.core.datamodel.PartManagement import ( - Root as PartManagement_root, + pm_module = importlib.import_module( + f"ansys.fluent.core.datamodel_{self.version}.PartManagement" ) - - self._part_management = PartManagement_root( + self._part_management = pm_module.Root( self._se_service, "PartManagement", [] ) except (ImportError, ModuleNotFoundError): @@ -101,11 +117,10 @@ def PMFileManagement(self): """PMFileManagement datamodel root.""" if self._pm_file_management is None: try: - from ansys.fluent.core.datamodel.PMFileManagement import ( - Root as PMFileManagement_root, + pmfm_module = importlib.import_module( + f"ansys.fluent.core.datamodel_{self.version}.PMFileManagement" ) - - self._pm_file_management = PMFileManagement_root( + self._pm_file_management = pmfm_module.Root( self._se_service, "PMFileManagement", [] ) except (ImportError, ModuleNotFoundError): diff --git a/src/ansys/fluent/core/session_solver.py b/src/ansys/fluent/core/session_solver.py index 4a32191bbb9..dd21c2aa8c2 100644 --- a/src/ansys/fluent/core/session_solver.py +++ b/src/ansys/fluent/core/session_solver.py @@ -1,8 +1,11 @@ """Module containing class encapsulating Fluent connection.""" +import importlib + from ansys.fluent.core.services.datamodel_tui import TUIMenuGeneric from ansys.fluent.core.session import _CODEGEN_MSG_TUI, _BaseSession from ansys.fluent.core.solver.flobject import get_root as settings_get_root +from ansys.fluent.core.utils.fluent_version import get_version_for_filepath from ansys.fluent.core.utils.logging import LOG @@ -20,6 +23,13 @@ def __init__( self._settings_service = self.fluent_connection.settings_service self._tui = None self._settings_root = None + self._version = None + + @property + def version(self): + if self._version is None: + self._version = get_version_for_filepath(session=self) + return self._version @property def tui(self): @@ -27,10 +37,11 @@ def tui(self): executed.""" if self._tui is None: try: - from ansys.fluent.core.solver.tui import main_menu as SolverMainMenu - - self._tui = SolverMainMenu([], self._tui_service) - except (ImportError, ModuleNotFoundError): + tui_module = importlib.import_module( + f"ansys.fluent.core.solver.tui_{self.version}" + ) + self._tui = tui_module.main_menu([], self._tui_service) + except ImportError: LOG.warning(_CODEGEN_MSG_TUI) self._tui = TUIMenuGeneric([], self._tui_service) return self._tui @@ -39,7 +50,9 @@ def tui(self): def _root(self): """root settings object.""" if self._settings_root is None: - self._settings_root = settings_get_root(flproxy=self._settings_service) + self._settings_root = settings_get_root( + flproxy=self._settings_service, version=self.version + ) return self._settings_root @property diff --git a/src/ansys/fluent/core/solver/flobject.py b/src/ansys/fluent/core/solver/flobject.py index f0053a1c124..38d50fbb520 100644 --- a/src/ansys/fluent/core/solver/flobject.py +++ b/src/ansys/fluent/core/solver/flobject.py @@ -17,6 +17,7 @@ """ import collections import hashlib +import importlib import keyword import pickle import string @@ -944,7 +945,7 @@ def _gethash(obj_info): return dhash.hexdigest() -def get_root(flproxy) -> Group: +def get_root(flproxy, version: str = "") -> Group: """Get the root settings object. Parameters @@ -958,7 +959,9 @@ def get_root(flproxy) -> Group: """ obj_info = flproxy.get_static_info() try: - from ansys.fluent.core.solver import settings + settings = importlib.import_module( + f"ansys.fluent.core.solver.settings_{version}" + ) if settings.SHASH != _gethash(obj_info): LOG.warning( diff --git a/src/ansys/fluent/core/utils/fluent_version.py b/src/ansys/fluent/core/utils/fluent_version.py new file mode 100644 index 00000000000..90a8cfa8111 --- /dev/null +++ b/src/ansys/fluent/core/utils/fluent_version.py @@ -0,0 +1,21 @@ +import os + +import ansys.fluent.core as pyfluent + + +def get_version(session=None): + if session is None: + # for CI runs, get the version statically from env var set within CI + image_tag = os.getenv("FLUENT_IMAGE_TAG") + if image_tag is not None: + return image_tag.lstrip("v") + session = pyfluent.launch_fluent(mode="solver") + + return session.get_fluent_version() + + +def get_version_for_filepath(version: str = None, session=None): + if version is None: + version = get_version(session) + + return "".join(version.split(".")[0:2])