Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142,258 changes: 142,258 additions & 0 deletions .ci/basedpyright.json

Large diffs are not rendered by default.

20 changes: 17 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,25 @@
token: ${{ secrets.GITHUB_TOKEN }}

code-style:
name: Code style
name: "Code style"
runs-on: ubuntu-latest
steps:
- name: "Run PyAnsys code style checks"
uses: ansys/actions/code-style@v10.2
- uses: ansys/actions/code-style@v10

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'GitHub Actions' step
Uses Step
uses 'ansys/actions/code-style' with ref 'v10', not a pinned commit hash
with:
python-version: ${{ env.MAIN_PYTHON_VERSION }}
skip-install: false

- name: "Make venv"
run: uv venv

- name: "Install basedpyright"
run: uv tool install basedpyright

- name: "Install extras"
run: uv pip install -e ".[ci_types]"

- name: "Check Type hints"
run: basedpyright

commit-style:
name: "Run commit style checks"
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ repos:
--statistics,
--max-complexity, "10",
--max-line-length, "88",
--extend-ignore, E203 E501 C901 B007 B009 B010 B011 B028,
--extend-ignore, E203 E501 C901 B007 B009 B010 B011 B028 F403 F405 F401 E402,
src, doc, examples, tests
]

Expand Down
Empty file added README.md
Empty file.
7 changes: 3 additions & 4 deletions devel/undocumented_fields/search_undocumented_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import os
import sys
from typing import Dict, Set

import ast_comments as ast

Expand Down Expand Up @@ -121,7 +120,7 @@ def visit_FunctionDef(self, node):
self.classes[self.current_class].add(child.target.attr)


def analyze_file(file_path: str) -> Dict[str, Set[str]]:
def analyze_file(file_path: str) -> dict[str, set[str]]:
"""Analyze a Python file and return classes with their public fields."""
with open(file_path, "r", encoding="utf-8") as file:
try:
Expand All @@ -134,7 +133,7 @@ def analyze_file(file_path: str) -> Dict[str, Set[str]]:
return {}


def analyze_package(package_path: str) -> Dict[str, Dict[str, Set[str]]]:
def analyze_package(package_path: str) -> dict[str, dict[str, set[str]]]:
"""Analyze all Python files in a package directory."""
result = {}

Expand All @@ -160,7 +159,7 @@ def analyze_package(package_path: str) -> Dict[str, Dict[str, Set[str]]]:
return result


def write_results(results: Dict[str, Dict[str, Set[str]]], f) -> str:
def write_results(results: dict[str, dict[str, set[str]]], f) -> None:
"""Format the analysis results."""
for module_name, classes in sorted(results.items()):

Expand Down
1 change: 1 addition & 0 deletions doc/changelog.d/4761.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Typing improvements
2 changes: 1 addition & 1 deletion doc/modify_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def modify_html(soup: BeautifulSoup) -> None:
/ "settings"
)
for html_file in html_dir.glob("*.html"):
with open(html_file, "r", encoding="utf-8") as f:
with open(html_file, encoding="utf-8") as f:
soup = BeautifulSoup(f, "html.parser", from_encoding="utf-8")

modify_html(soup)
Expand Down
13 changes: 6 additions & 7 deletions examples/00-fluent/DOE_ML.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
# flake8: noqa: E402

import os
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
Expand Down Expand Up @@ -264,8 +263,8 @@
def display_scores(scores):
"""Display scores."""
print("\nCross-Validation Scores:", scores)
print("Mean:%0.2f" % (scores.mean()))
print("Std. Dev.:%0.2f" % (scores.std()))
print(f"Mean:{scores.mean():0.2f}")
print(f"Std. Dev.:{scores.std():0.2f}")


def fit_and_predict(model):
Expand All @@ -282,8 +281,8 @@ def fit_and_predict(model):
test_predictions = model.predict(X_test)
print(train_predictions.shape[0])
print("\n\nCoefficient Of Determination")
print("Train Data R2 Score: %0.3f" % (r2_score(train_predictions, y_train)))
print("Test Data R2 Score: %0.3f" % (r2_score(test_predictions, y_test)))
print(f"Train Data R2 Score: {r2_score(train_predictions, y_train):0.3f}")
print(f"Test Data R2 Score: {r2_score(test_predictions, y_test):0.3f}")
print(
"\n\nPredictions - Ground Truth (Kelvin): ", (test_predictions - y_test), "\n"
)
Expand Down Expand Up @@ -451,8 +450,8 @@ def fit_and_predict(model):
test_predictions = np.ravel(test_predictions.T)
print(test_predictions.shape)

print("\n\nTrain R2: %0.3f" % (r2_score(train_predictions, y_train)))
print("Test R2: %0.3f" % (r2_score(test_predictions, y_test)))
print(f"\n\nTrain R2: {r2_score(train_predictions, y_train):0.3f}")
print(f"Test R2: {r2_score(test_predictions, y_test):0.3f}")
print("Predictions - Ground Truth (Kelvin): ", (test_predictions - y_test))

fig = plt.figure(figsize=(12, 5))
Expand Down
10 changes: 10 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies = [
"pandas>=1.1.0,<3.0.0",
"pyansys-tools-report>=0.8.1",
"pyyaml>=6.0",
"typing-extensions>=4.12"
]
dynamic = ["version"]

Expand Down Expand Up @@ -234,3 +235,12 @@ skips = [
"B604",
"B607",
]

[tool.basedpyright]
reportAny = false
reportUnknownMemberType = false
reportExplicitAny = false
reportPrivateUsage = false
reportUnusedCallResult = false
ignore = ["doc", "src/ansys/fluent/core/generated"]
baselineFile = ".ci/basedpyright.json"
105 changes: 41 additions & 64 deletions src/ansys/fluent/core/__init__.py
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change to star imports makes everything exported as public to to typechecker

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gobot1234 We can't lose control over the public API.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry if it wasn't clear you don't the modules define a dunder all and that's how public symbols are decided there is no regression in pyfluent's list of publicly available symbols

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Gobot1234
Can you kindly explain the last comment in more detail. I was not able to understand it properly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gobot1234 OK, I didn't see that you had added those, and I confirm that I see those now. I can ask @mayankansys to add a test for dir() at the top-level where the expected result is based on current behaviour. Or does such a test exist?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Gobot1234 Can you kindly explain the last comment in more detail. I was not able to understand it properly.

A little on `__all__` if you weren't sure about that

Python has a special symbol __all__ which is a sequence of str at the module level which defines the symbols that get imported when you do from ... import *. This stops things leaking into the module scope. Normally it just gets all attributes that don't have a leading underscore in the module

This is the result of adding the all to the submodules (it should look basically no different), I have however adjusted some of the imports in pyfluent that aren't meant to be there.

>>> dir()
['PS1', 'REPLHooks', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'get_last_command', 'is_wsl', 'original_ps1', 'platform', 'sys']
>>> import ansys.fluent.core as pyfluent
>>> dir(pyfluent)                       
['AboutToInitializeSolutionEventInfo', 'AboutToLoadCaseEventInfo', 'AboutToLoadDataEventInfo', 'BaseSession', 'BatchOps', 'CalculationsEndedEventInfo', 'CalculationsPausedEventInfo', 'CalculationsResumedEventInfo', 'CalculationsStartedEventInfo', 'CaseLoadedEventInfo', 'DataLoadedEventInfo', 'Dimension', 'Event', 'EventsManager', 'FatalErrorEventInfo', 'Fluent', 'FluentDevVersionWarning', 'FluentLinuxGraphicsDriver', 'FluentMode', 'FluentVersion', 'FluentWindowsGraphicsDriver', 'IterationEndedEventInfo', 'LocalParametricStudy', 'Meshing', 'MeshingEvent', 'PathlinesFieldDataRequest', 'PrePost', 'Precision', 'ProgressUpdatedEventInfo', 'PureMeshing', 'PyFluentDeprecationWarning', 'PyFluentUserWarning', 'ReportDefinitionUpdatedEventInfo', 'ReportPlotSetUpdatedEventInfo', 'ResidualPlotUpdatedEventInfo', 'ScalarFieldDataRequest', 'SettingsClearedEventInfo', 'SolutionInitializedEventInfo', 'SolutionPausedEventInfo', 'Solver', 'SolverAero', 'SolverEvent', 'SolverIcing', 'SolverTimeEstimateUpdatedEventInfo', 'SurfaceDataType', 'SurfaceFieldDataRequest', 'TimestepEndedEventInfo', 'TimestepStartedEventInfo', 'UIMode', 'VectorFieldDataRequest', '_README_FILE', '_THIS_DIRNAME', '_TYPE_CHECKING', '_VERSION_INFO', '__builtins__', '__cached__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_config_by_deprecated_name', '_fldoc', '_os', '_pydoc', '_types', '_warnings', 'config', 'create_launcher', 'data_model_cache', 'docker', 'exceptions', 'field_data_interfaces', 'filereader', 'fluent_connection', 'get_build_details', 'get_build_version', 'get_build_version_string', 'get_user_data_dir', 'journaling', 'launch_fluent', 'launcher', 'load_module', 'logger', 'meshing', 'module_config', 'parametric', 'pyfluent_warnings', 'rpvars', 'scheduler', 'search', 'services', 'session', 'session_base_meshing', 'session_meshing', 'session_pure_meshing', 'session_shared', 'session_solver', 'session_solver_aero', 'session_solver_icing', 'session_utilities', 'set_console_logging_level', 'setup_for_fluent', 'solver', 'streaming_services', 'system_coupling', 'utils', 'variable_strategies', 'version_info', 'warning', 'workflow', 'workflow_new']
>>> from ansys.fluent.core import *
>>> dir()
['AboutToInitializeSolutionEventInfo', 'AboutToLoadCaseEventInfo', 'AboutToLoadDataEventInfo', 'BaseSession', 'BatchOps', 'CalculationsEndedEventInfo', 'CalculationsPausedEventInfo', 'CalculationsResumedEventInfo', 'CalculationsStartedEventInfo', 'CaseLoadedEventInfo', 'DataLoadedEventInfo', 'Dimension', 'Event', 'EventsManager', 'FatalErrorEventInfo', 'Fluent', 'FluentDevVersionWarning', 'FluentLinuxGraphicsDriver', 'FluentMode', 'FluentVersion', 'FluentWindowsGraphicsDriver', 'IterationEndedEventInfo', 'LocalParametricStudy', 'Meshing', 'MeshingEvent', 'PS1', 'PathlinesFieldDataRequest', 'PrePost', 'Precision', 'ProgressUpdatedEventInfo', 'PureMeshing', 'PyFluentDeprecationWarning', 'PyFluentUserWarning', 'REPLHooks', 'ReportDefinitionUpdatedEventInfo', 'ReportPlotSetUpdatedEventInfo', 'ResidualPlotUpdatedEventInfo', 'ScalarFieldDataRequest', 'SettingsClearedEventInfo', 'SolutionInitializedEventInfo', 'SolutionPausedEventInfo', 'Solver', 'SolverAero', 'SolverEvent', 'SolverIcing', 'SolverTimeEstimateUpdatedEventInfo', 'SurfaceDataType', 'SurfaceFieldDataRequest', 'TimestepEndedEventInfo', 'TimestepStartedEventInfo', 'UIMode', 'VectorFieldDataRequest', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'config', 'create_launcher', 'data_model_cache', 'docker', 'exceptions', 'field_data_interfaces', 'filereader', 'fluent_connection', 'get_build_details', 'get_build_version', 'get_build_version_string', 'get_last_command', 'get_user_data_dir', 'is_wsl', 'journaling', 'launch_fluent', 'launcher', 'load_module', 'logger', 'meshing', 'module_config', 'original_ps1', 'parametric', 'platform', 'pyfluent', 'pyfluent_warnings', 'rpvars', 'scheduler', 'search', 'services', 'session', 'session_base_meshing', 'session_meshing', 'session_pure_meshing', 'session_shared', 'session_solver', 'session_solver_aero', 'session_solver_icing', 'session_utilities', 'set_console_logging_level', 'setup_for_fluent', 'solver', 'streaming_services', 'sys', 'system_coupling', 'utils', 'variable_strategies', 'version_info', 'warning', 'workflow', 'workflow_new']

Original file line number Diff line number Diff line change
Expand Up @@ -22,64 +22,31 @@

"""A package providing Fluent's Solver and Meshing capabilities in Python."""

import os
import pydoc
import warnings

# isort: off

# config must be initialized before logging setup.
from ansys.fluent.core.module_config import config
from ansys.fluent.core.module_config import *

# Logging has to be imported before importing other PyFluent modules
from ansys.fluent.core.logger import set_console_logging_level # noqa: F401
from ansys.fluent.core.logger import *

# isort: on

from ansys.fluent.core.field_data_interfaces import ( # noqa: F401
PathlinesFieldDataRequest,
ScalarFieldDataRequest,
SurfaceDataType,
SurfaceFieldDataRequest,
VectorFieldDataRequest,
)
from ansys.fluent.core.get_build_details import ( # noqa: F401
get_build_version,
get_build_version_string,
)
from ansys.fluent.core.launcher.launch_options import ( # noqa: F401
Dimension,
FluentLinuxGraphicsDriver,
FluentMode,
FluentWindowsGraphicsDriver,
Precision,
UIMode,
)
from ansys.fluent.core.launcher.launcher import ( # noqa: F401
connect_to_fluent,
launch_fluent,
)
from ansys.fluent.core.parametric import LocalParametricStudy # noqa: F401
from ansys.fluent.core.pyfluent_warnings import ( # noqa: F401
PyFluentDeprecationWarning,
PyFluentUserWarning,
warning,
)
from ansys.fluent.core.search import search # noqa: F401
from ansys.fluent.core.services.batch_ops import BatchOps # noqa: F401
from ansys.fluent.core.session import BaseSession as Fluent # noqa: F401
from ansys.fluent.core.session_utilities import ( # noqa: F401
Meshing,
PrePost,
PureMeshing,
Solver,
SolverAero,
SolverIcing,
)
from ansys.fluent.core.streaming_services.events_streaming import * # noqa: F401, F403
from ansys.fluent.core.utils import fldoc
from ansys.fluent.core.utils.fluent_version import FluentVersion # noqa: F401
from ansys.fluent.core.utils.setup_for_fluent import setup_for_fluent # noqa: F401
from ansys.fluent.core.field_data_interfaces import *
from ansys.fluent.core.get_build_details import *
from ansys.fluent.core.launcher.launch_options import *
from ansys.fluent.core.launcher.launcher import *
from ansys.fluent.core.parametric import *
from ansys.fluent.core.pyfluent_warnings import *
from ansys.fluent.core.search import *
from ansys.fluent.core.services.batch_ops import *
from ansys.fluent.core.session import *
from ansys.fluent.core.session import BaseSession as Fluent
from ansys.fluent.core.session_utilities import *
from ansys.fluent.core.streaming_services.events_streaming import *
from ansys.fluent.core.utils import *
from ansys.fluent.core.utils.fluent_version import *
from ansys.fluent.core.utils.setup_for_fluent import *

__version__ = "0.38.dev2"

Expand All @@ -89,10 +56,14 @@
Build timestamp and commit hash are added to this variable during packaging.
"""

_THIS_DIRNAME = os.path.dirname(__file__)
_README_FILE = os.path.normpath(os.path.join(_THIS_DIRNAME, "docs", "README.rst"))
import os as _os # noqa: E402
import warnings as _warnings # noqa: E402


_THIS_DIRNAME = _os.path.dirname(__file__)
_README_FILE = _os.path.normpath(_os.path.join(_THIS_DIRNAME, "docs", "README.rst"))

if os.path.exists(_README_FILE):
if _os.path.exists(_README_FILE):
with open(_README_FILE, encoding="utf8") as f:
__doc__ = f.read()

Expand All @@ -112,7 +83,10 @@ def version_info() -> str:
return _VERSION_INFO if _VERSION_INFO is not None else __version__


pydoc.text.docother = fldoc.docother.__get__(pydoc.text, pydoc.TextDoc)
import pydoc as _pydoc # noqa: E402
from ansys.fluent.core.utils import fldoc as _fldoc # noqa: E402

_pydoc.text.docother = _fldoc.docother.__get__(_pydoc.text, _pydoc.TextDoc)


_config_by_deprecated_name = {
Expand Down Expand Up @@ -144,14 +118,17 @@ def version_info() -> str:
"LAUNCH_FLUENT_SKIP_PASSWORD_CHECK": "launch_fluent_skip_password_check",
}

from typing import TYPE_CHECKING as _TYPE_CHECKING # noqa: E402

if not _TYPE_CHECKING:

def __getattr__(name: str) -> str:
"""Get the value of a deprecated configuration variable."""
if name in _config_by_deprecated_name:
config_name = _config_by_deprecated_name[name]
warnings.warn(
f"'{name}' is deprecated, use 'config.{config_name}' instead.",
category=PyFluentDeprecationWarning,
)
return getattr(config, config_name)
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
def __getattr__(name: str) -> str:
"""Get the value of a deprecated configuration variable."""
if name in _config_by_deprecated_name:
config_name = _config_by_deprecated_name[name]
_warnings.warn(
f"'{name}' is deprecated, use 'config.{config_name}' instead.",
category=PyFluentDeprecationWarning,
)
return getattr(config, config_name)
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
2 changes: 1 addition & 1 deletion src/ansys/fluent/core/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
import os
from typing import TypeAlias

PathType: TypeAlias = "os.PathLike[str] | os.PathLike[bytes] | str | bytes"
PathType: TypeAlias = "os.PathLike[str] | str"
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing bytes and os.PathLike[bytes] from PathType is a breaking change that could affect existing code passing bytes paths. This should be documented in the changelog or reconsidered if bytes paths are used in the codebase.

Suggested change
PathType: TypeAlias = "os.PathLike[str] | str"
PathType: TypeAlias = "os.PathLike[str] | os.PathLike[bytes] | str | bytes"

Copilot uses AI. Check for mistakes.
"""Type alias for file system paths."""
4 changes: 2 additions & 2 deletions src/ansys/fluent/core/codegen/datamodelgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from pathlib import Path
import shutil
import string
from typing import Any, Dict
from typing import Any

import ansys.fluent.core as pyfluent
from ansys.fluent.core import FluentMode, launch_fluent
Expand Down Expand Up @@ -230,7 +230,7 @@ class DataModelGenerator:
def __init__(self, version, static_infos: dict, verbose: bool = False):
self.version = version
self._server_static_infos = static_infos
self._static_info: Dict[str, DataModelStaticInfo] = {}
self._static_info: dict[str, DataModelStaticInfo] = {}
self._verbose = verbose
if StaticInfoType.DATAMODEL_WORKFLOW in static_infos:
self._static_info["workflow"] = DataModelStaticInfo(
Expand Down
6 changes: 3 additions & 3 deletions src/ansys/fluent/core/codegen/tuigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
import shutil
import string
import subprocess
from typing import Any, Dict
from typing import Any
import uuid

from defusedxml.ElementTree import parse
Expand Down Expand Up @@ -194,7 +194,7 @@ def find_class(self, module, name):
if module == "tuigen":
renamed_module = "ansys.fluent.core.codegen.tuigen"

return super(_RenameModuleUnpickler, self).find_class(renamed_module, name)
return super().find_class(renamed_module, name)


class TUIGenerator:
Expand All @@ -217,7 +217,7 @@ def __init__(
self._static_infos = static_infos
self._verbose = verbose

def _populate_menu(self, menu: _TUIMenu, info: Dict[str, Any]):
def _populate_menu(self, menu: _TUIMenu, info: dict[str, Any]):
for child_menu_name, child_menu_info in sorted(info["menus"].items()):
if _is_valid_tui_menu_name(child_menu_name):
child_menu = _TUIMenu(
Expand Down
3 changes: 1 addition & 2 deletions src/ansys/fluent/core/codegen/walk_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@
"""

from inspect import signature
from typing import List

import ansys.fluent.core.solver.flobject as flobject


def walk_api(
api_cls, on_each_path, current_path: str | List[str] = "", api_item_type: str = ""
api_cls, on_each_path, current_path: str | list[str] = "", api_item_type: str = ""
):
"""
Recursively traverse the API hierarchy, calling `on_each_path` for each item.
Expand Down
Loading
Loading