Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ansys/pyfluent
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.12.dev3
Choose a base ref
...
head repository: ansys/pyfluent
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Loading
Showing 586 changed files with 86,833 additions and 53,987 deletions.
31 changes: 0 additions & 31 deletions .ci/compare_flobject.py

This file was deleted.

168 changes: 168 additions & 0 deletions .ci/fluent_test_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"""Script to run Fluent test in Docker container."""

import argparse
import concurrent.futures
import logging
import os
from pathlib import Path
from shutil import copytree
from tempfile import TemporaryDirectory
from time import sleep

import yaml

import ansys.fluent.core as pyfluent
from ansys.fluent.core import FluentVersion
import docker


class FluentRuntimeError(RuntimeError):
"""Exception raised when stderr is detected in Fluent output."""

pass


def _run_single_test(
src_test_dir: Path, journal_file: Path, launcher_args: str
) -> None:
"""Run a single Fluent test.
Parameters
----------
src_test_dir : Path
Path to the Fluent test directory in the host.
journal_file : Path
Absolute path to the journal file.
launcher_args : str, optional
Additional arguments for the Fluent launcher.
Raises
------
FluentRuntimeError
Raised when stderr is detected in Fluent output.
"""
logging.debug(f"journal_file: {journal_file}")
src_pyfluent_dir = str(Path(pyfluent.__file__).parent)
verion_for_file_name = FluentVersion.current_dev().number
dst_pyfluent_dir = f"/ansys_inc/v{verion_for_file_name}/commonfiles/CPython/3_10/linx64/Release/Ansys/PyFluentCore/ansys/fluent/core"
src_gen_dir = (
Path(pyfluent.__file__).parent / "ansys" / "fluent" / "core" / "generated"
)
dst_gen_dir = f"/ansys_inc/v{verion_for_file_name}/fluent/fluent{FluentVersion.current_dev()!r}/cortex/pylib/flapi/generated"
dst_test_dir = "/testing"
working_dir = Path(dst_test_dir)
parent = journal_file.parent
parents = []
while parent != src_test_dir:
parents.append(parent.name)
parent = parent.parent
parents.reverse()
for parent in parents:
working_dir /= parent
working_dir = str(working_dir)
src_test_dir = str(src_test_dir)
logging.debug(f"src_pyfluent_dir: {src_pyfluent_dir}")
logging.debug(f"dst_pyfluent_dir: {dst_pyfluent_dir}")
logging.debug(f"src_test_dir: {src_test_dir}")
logging.debug(f"dst_test_dir: {dst_test_dir}")
logging.debug(f"working_dir: {working_dir}")

docker_client = docker.from_env()
version_for_image_tag = FluentVersion.current_dev().docker_image_tag
image_name = f"ghcr.io/ansys/fluent:{version_for_image_tag}"
container = docker_client.containers.run(
image=image_name,
volumes=[
f"{src_pyfluent_dir}:{dst_pyfluent_dir}",
f"{src_gen_dir}:{dst_gen_dir}", # Try removing this after pyfluent is updated in commonfiles
f"{src_test_dir}:{dst_test_dir}",
],
working_dir=working_dir,
environment={"ANSYSLMD_LICENSE_FILE": os.environ["ANSYSLMD_LICENSE_FILE"]},
command=f"{launcher_args} -gu -py -i {journal_file.name}",
detach=True,
stdout=True,
stderr=True,
auto_remove=True,
)
try:
while True:
container.reload()
if container.status == "exited":
break
stderr = container.logs(stdout=False, stderr=True)
if stderr:
stderr = stderr.decode()
for line in stderr.splitlines():
if line.strip().startswith("Error:"):
if "Expected exception" in line: # for check_assert.py
container.stop()
else:
raise FluentRuntimeError(stderr)
sleep(1)
print(container.logs(stderr=True).decode())
container.remove()
except docker.errors.DockerException:
pass


MAX_TEST_PATH_LENGTH = 100


def _run_single_test_with_status_print(
src_test_dir: Path, journal_file: Path, launcher_args: str, test_file_relpath: str
) -> bool:
try:
_run_single_test(src_test_dir, journal_file, launcher_args)
print(
f"{test_file_relpath}{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}PASSED"
)
except FluentRuntimeError as e:
print(
f"{test_file_relpath}{(MAX_TEST_PATH_LENGTH + 10 - len(test_file_relpath)) * '·'}FAILED"
)
print(e)
return True


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run Fluent test.")
parser.add_argument(
"test_dir",
help="Path to the Fluent test directory relative to the PyFluent repository root.",
)
args = parser.parse_args()
test_dir = Path.cwd() / args.test_dir
with TemporaryDirectory(ignore_cleanup_errors=True) as src_test_dir:
copytree(test_dir, src_test_dir, dirs_exist_ok=True)
statuses = []
arguments = []
src_test_dir = Path(src_test_dir)
for test_file in (src_test_dir / "fluent").rglob("*.py"):
config_file = test_file.with_suffix(".yaml")
launcher_args = ""
if config_file.exists():
configs = yaml.safe_load(config_file.read_text())
launcher_args = configs.get("launcher_args", "")
test_file_relpath = str(test_file.relative_to(src_test_dir))
arguments.append(
(src_test_dir, test_file, launcher_args, test_file_relpath)
)
max_workers = int(os.getenv("MAX_WORKERS_FLUENT_TESTS", 4))
if max_workers > 1:
with concurrent.futures.ThreadPoolExecutor(
max_workers=max_workers
) as executor:
futures = [
executor.submit(_run_single_test_with_status_print, *args)
for args in arguments
]
for future in concurrent.futures.as_completed(futures):
statuses.append(future.result())
else:
for args in arguments:
statuses.append(_run_single_test_with_status_print(*args))
if any(statuses):
exit(1)
72 changes: 72 additions & 0 deletions .ci/get_hanging_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""A script to print the name of the hanging test by parsing the GitHub logs file."""

import argparse


def strip_before_tests(input_string):
"""
Strips everything before the 'tests/' in the given string.
Parameters
----------
input_string: str
The original string to process.
Returns
-------
The modified string.
"""
index = input_string.find("tests/")
if index != -1:
return input_string[index:]


def parse_github_log(log_file_path: str) -> str:
"""
Parse GitHub log lines to identify hanging tests.
Parameters
----------
log_file_path: str
The path of the log file from GitHub.
Returns
-------
Name of the haging tests.
"""
tests = {}
hanging_tests = []

with open(log_file_path, "r", encoding="utf-8") as f:
log_lines = f.readlines()

for line in log_lines:
test_name = strip_before_tests(line)
if test_name:
if tests.get(test_name):
tests[test_name] += 1
else:
tests[test_name] = 1

for key, value in tests.items():
if value != 2:
hanging_tests.append(key)

return hanging_tests


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="A script to print the name of the hanging test by parsing the GitHub logs file."
)
parser.add_argument(
"-logfile",
type=str,
help="Path of the log file.",
)
args = parser.parse_args()
hanging_tests = parse_github_log(args.logfile)
if hanging_tests:
print("\n Hanging tests detected.\n")
for test in hanging_tests:
print(test)
else:
print("No hanging tests detected.")
22 changes: 22 additions & 0 deletions .ci/pull_fluent_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
Pull a Fluent Docker image based on the FLUENT_IMAGE_TAG environment variable.
"""

import subprocess

from ansys.fluent.core import config
from ansys.fluent.core.docker.utils import get_ghcr_fluent_image_name


def pull_fluent_image():
"""Pull Fluent Docker image and clean up dangling images."""
fluent_image_tag = config.fluent_image_tag
image_name = get_ghcr_fluent_image_name(fluent_image_tag)
separator = "@" if fluent_image_tag.startswith("sha256") else ":"
full_image_name = f"{image_name}{separator}{fluent_image_tag}"
subprocess.run(["docker", "pull", full_image_name], check=True)
subprocess.run(["docker", "image", "prune", "-f"], check=True)


if __name__ == "__main__":
pull_fluent_image()
10 changes: 0 additions & 10 deletions .ci/pull_fluent_image.sh

This file was deleted.

4 changes: 4 additions & 0 deletions .codacy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
languages:
python:
enabled: false
2 changes: 0 additions & 2 deletions .coveragerc

This file was deleted.

9 changes: 4 additions & 5 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
[flake8]
exclude = venv, doc/_build, 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/*
max-line-length = 88
exclude = src/ansys/fluent/core/generated
count = True
max-complexity = 10
statistics = True
select = W191 W291 W293 W391 E115 E117 E122 E124 E125 E225 E231 E301 E303 F401 F403 N801 N802 N803 N804 N805 N806
extend-ignore = E203, E501
max-complexity = 10
max-line-length = 88
extend-ignore = E203, E501, C901
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -3,3 +3,4 @@
*.bat eol=crlf
*.py text
*.json text
*.zip filter=lfs diff=lfs merge=lfs -text
22 changes: 16 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/requirements" # Location of package manifests
directory: "/" # Location of package manifests
insecure-external-code-execution: allow
schedule:
interval: "daily"
interval: "monthly"
labels:
- "Maintenance"
- "Dependencies"
ignore:
- dependency-name: "vtk"
- dependency-name: "grpcio"
groups:
dependencies:
patterns:
- "*"
update-types:
- "minor"
- "patch"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
interval: "monthly"
labels:
- "Maintenance"
groups:
actions:
patterns:
- "*"
Loading