ansys-fluent-core 0.34.2__py3-none-any.whl → 0.35.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansys-fluent-core might be problematic. Click here for more details.

Files changed (82) hide show
  1. ansys/fluent/core/__init__.py +48 -84
  2. ansys/fluent/core/codegen/allapigen.py +2 -2
  3. ansys/fluent/core/codegen/builtin_settingsgen.py +54 -28
  4. ansys/fluent/core/codegen/datamodelgen.py +3 -1
  5. ansys/fluent/core/codegen/print_fluent_version.py +2 -2
  6. ansys/fluent/core/codegen/settingsgen.py +4 -1
  7. ansys/fluent/core/codegen/tuigen.py +4 -4
  8. ansys/fluent/core/data_model_cache.py +2 -2
  9. ansys/fluent/core/docker/docker_compose.py +8 -9
  10. ansys/fluent/core/docker/utils.py +2 -2
  11. ansys/fluent/core/examples/downloads.py +8 -11
  12. ansys/fluent/core/fluent_connection.py +23 -15
  13. ansys/fluent/core/generated/api_tree/api_objects.json +1 -1
  14. ansys/fluent/core/generated/datamodel_231/flicing.py +50 -50
  15. ansys/fluent/core/generated/datamodel_231/meshing.py +182 -182
  16. ansys/fluent/core/generated/datamodel_232/flicing.py +45 -45
  17. ansys/fluent/core/generated/datamodel_232/meshing.py +172 -172
  18. ansys/fluent/core/generated/datamodel_241/flicing.py +45 -45
  19. ansys/fluent/core/generated/datamodel_241/meshing.py +303 -303
  20. ansys/fluent/core/generated/datamodel_242/flicing.py +50 -50
  21. ansys/fluent/core/generated/datamodel_242/meshing.py +309 -309
  22. ansys/fluent/core/generated/datamodel_242/part_management.py +3 -3
  23. ansys/fluent/core/generated/datamodel_251/flicing.py +50 -50
  24. ansys/fluent/core/generated/datamodel_251/meshing.py +327 -327
  25. ansys/fluent/core/generated/datamodel_251/part_management.py +9 -9
  26. ansys/fluent/core/generated/datamodel_252/flicing.py +30 -30
  27. ansys/fluent/core/generated/datamodel_252/meshing.py +370 -370
  28. ansys/fluent/core/generated/datamodel_252/part_management.py +15 -15
  29. ansys/fluent/core/generated/datamodel_261/flicing.py +35 -35
  30. ansys/fluent/core/generated/datamodel_261/meshing.py +444 -388
  31. ansys/fluent/core/generated/datamodel_261/part_management.py +5 -5
  32. ansys/fluent/core/generated/datamodel_261/preferences.py +28 -0
  33. ansys/fluent/core/generated/fluent_version_261.py +3 -3
  34. ansys/fluent/core/generated/meshing/tui_261.py +1247 -1136
  35. ansys/fluent/core/generated/solver/settings_261.py +9912 -4184
  36. ansys/fluent/core/generated/solver/settings_261.pyi +6779 -3312
  37. ansys/fluent/core/generated/solver/settings_builtin.py +515 -27
  38. ansys/fluent/core/generated/solver/settings_builtin.pyi +2 -18
  39. ansys/fluent/core/generated/solver/tui_261.py +4439 -3245
  40. ansys/fluent/core/launcher/container_launcher.py +19 -4
  41. ansys/fluent/core/launcher/fluent_container.py +51 -39
  42. ansys/fluent/core/launcher/launch_options.py +5 -4
  43. ansys/fluent/core/launcher/launcher.py +16 -3
  44. ansys/fluent/core/launcher/launcher_utils.py +63 -15
  45. ansys/fluent/core/launcher/pim_launcher.py +17 -3
  46. ansys/fluent/core/launcher/process_launch_string.py +3 -2
  47. ansys/fluent/core/launcher/server_info.py +7 -3
  48. ansys/fluent/core/launcher/slurm_launcher.py +4 -3
  49. ansys/fluent/core/launcher/standalone_launcher.py +6 -3
  50. ansys/fluent/core/launcher/watchdog.py +3 -3
  51. ansys/fluent/core/launcher/watchdog_exec +1 -1
  52. ansys/fluent/core/logger.py +3 -1
  53. ansys/fluent/core/module_config.py +363 -0
  54. ansys/fluent/core/pyfluent_warnings.py +2 -2
  55. ansys/fluent/core/report.py +0 -2
  56. ansys/fluent/core/search.py +43 -18
  57. ansys/fluent/core/services/api_upgrade.py +3 -2
  58. ansys/fluent/core/services/datamodel_se.py +4 -2
  59. ansys/fluent/core/services/health_check.py +3 -1
  60. ansys/fluent/core/services/interceptors.py +8 -6
  61. ansys/fluent/core/session.py +31 -3
  62. ansys/fluent/core/session_pure_meshing.py +1 -1
  63. ansys/fluent/core/session_shared.py +4 -4
  64. ansys/fluent/core/session_solver.py +13 -6
  65. ansys/fluent/core/session_utilities.py +7 -0
  66. ansys/fluent/core/solver/flobject.py +6 -4
  67. ansys/fluent/core/solver/flunits.py +2 -0
  68. ansys/fluent/core/solver/settings_builtin_bases.py +3 -3
  69. ansys/fluent/core/solver/settings_builtin_data.py +2 -14
  70. ansys/fluent/core/streaming_services/datamodel_event_streaming.py +3 -2
  71. ansys/fluent/core/streaming_services/datamodel_streaming.py +3 -1
  72. ansys/fluent/core/streaming_services/events_streaming.py +2 -18
  73. ansys/fluent/core/system_coupling.py +3 -1
  74. ansys/fluent/core/utils/__init__.py +0 -7
  75. ansys/fluent/core/utils/data_transfer.py +3 -3
  76. ansys/fluent/core/utils/file_transfer_service.py +24 -15
  77. ansys/fluent/core/utils/fluent_version.py +3 -3
  78. ansys/fluent/core/utils/networking.py +13 -4
  79. {ansys_fluent_core-0.34.2.dist-info → ansys_fluent_core-0.35.dev1.dist-info}/METADATA +8 -7
  80. {ansys_fluent_core-0.34.2.dist-info → ansys_fluent_core-0.35.dev1.dist-info}/RECORD +82 -81
  81. {ansys_fluent_core-0.34.2.dist-info → ansys_fluent_core-0.35.dev1.dist-info}/WHEEL +1 -1
  82. {ansys_fluent_core-0.34.2.dist-info → ansys_fluent_core-0.35.dev1.dist-info/licenses}/LICENSE +0 -0
@@ -23,10 +23,14 @@
23
23
  """A package providing Fluent's Solver and Meshing capabilities in Python."""
24
24
 
25
25
  import os
26
- from pathlib import Path
27
26
  import pydoc
27
+ import warnings
28
28
 
29
29
  # isort: off
30
+
31
+ # config must be initialized before logging setup.
32
+ from ansys.fluent.core.module_config import config
33
+
30
34
  # Logging has to be imported before importing other PyFluent modules
31
35
  from ansys.fluent.core.logger import set_console_logging_level # noqa: F401
32
36
 
@@ -73,13 +77,13 @@ from ansys.fluent.core.session_utilities import ( # noqa: F401
73
77
  SolverIcing,
74
78
  )
75
79
  from ansys.fluent.core.streaming_services.events_streaming import * # noqa: F401, F403
76
- from ansys.fluent.core.utils import fldoc, get_examples_download_dir
80
+ from ansys.fluent.core.utils import fldoc
77
81
  from ansys.fluent.core.utils.fluent_version import FluentVersion # noqa: F401
78
82
  from ansys.fluent.core.utils.setup_for_fluent import setup_for_fluent # noqa: F401
79
83
 
80
- __version__ = "0.34.2"
84
+ __version__ = "0.35.dev1"
81
85
 
82
- _VERSION_INFO = "Build date: August 14, 2025 01:33 UTC ShaID: d5ae1e6"
86
+ _VERSION_INFO = "Build date: August 28, 2025 18:16 UTC ShaID: b1f9dbd"
83
87
  """
84
88
  Global variable indicating the version info of the PyFluent package.
85
89
  Build timestamp and commit hash are added to this variable during packaging.
@@ -108,86 +112,46 @@ def version_info() -> str:
108
112
  return _VERSION_INFO if _VERSION_INFO is not None else __version__
109
113
 
110
114
 
111
- # Latest released Fluent version
112
- FLUENT_RELEASE_VERSION = "25.2.0"
113
-
114
- # Current dev Fluent version
115
- FLUENT_DEV_VERSION = "26.1.0"
116
-
117
- # Path to the example input/data files are downloaded
118
- EXAMPLES_PATH = str(get_examples_download_dir())
119
-
120
- # Host path which is mounted to the container
121
- CONTAINER_MOUNT_SOURCE = None
122
-
123
- # Path inside the container where the host path is mounted
124
- CONTAINER_MOUNT_TARGET = "/home/container/workdir"
125
-
126
- # Set this to False to stop automatically inferring and setting REMOTING_SERVER_ADDRESS
127
- INFER_REMOTING_IP = True
128
-
129
- # Time in second to wait for response for each ip while inferring remoting ip
130
- INFER_REMOTING_IP_TIMEOUT_PER_IP = 2
131
-
132
115
  pydoc.text.docother = fldoc.docother.__get__(pydoc.text, pydoc.TextDoc)
133
116
 
134
- # Whether to use datamodel state caching
135
- DATAMODEL_USE_STATE_CACHE = True
136
-
137
- # Whether to use datamodel attribute caching
138
- DATAMODEL_USE_ATTR_CACHE = True
139
-
140
- # Whether to stream and cache commands state
141
- DATAMODEL_USE_NOCOMMANDS_DIFF_STATE = True
142
-
143
- # Whether to return the state changes on mutating datamodel rpcs
144
- DATAMODEL_RETURN_STATE_CHANGES = True
145
-
146
- # Whether to use remote gRPC file transfer service
147
- USE_FILE_TRANSFER_SERVICE = False
148
-
149
- # Directory where API files are written out during codegen
150
- CODEGEN_OUTDIR = os.getenv(
151
- "PYFLUENT_CODEGEN_OUTDIR", (Path(__file__) / ".." / "generated").resolve()
152
- )
153
-
154
- # Whether to show mesh in Fluent after case read
155
- FLUENT_SHOW_MESH_AFTER_CASE_READ = False
156
-
157
- # Whether to write the automatic transcript in Fluent
158
- FLUENT_AUTOMATIC_TRANSCRIPT = os.getenv("PYFLUENT_FLUENT_AUTOMATIC_TRANSCRIPT") == "1"
159
-
160
- # Whether to interrupt Fluent solver from PyFluent
161
- SUPPORT_SOLVER_INTERRUPT = False
162
-
163
- # Whether to start watchdog
164
- START_WATCHDOG = None
165
-
166
- # Health check timeout in seconds
167
- CHECK_HEALTH_TIMEOUT = 60
168
-
169
- # Whether to skip health check
170
- CHECK_HEALTH = True
171
-
172
- # Whether to print search results
173
- PRINT_SEARCH_RESULTS = True
174
-
175
- # Whether to clear environment variables related to Fluent parallel mode
176
- CLEAR_FLUENT_PARA_ENVS = False
177
-
178
- # Set stdout of the launched Fluent process
179
- # Valid values are same as subprocess.Popen's stdout argument
180
- LAUNCH_FLUENT_STDOUT = None
181
-
182
- # Set stderr of the launched Fluent process
183
- # Valid values are same as subprocess.Popen's stderr argument
184
- LAUNCH_FLUENT_STDERR = None
185
-
186
- # Set the IP address of the Fluent server while launching Fluent
187
- LAUNCH_FLUENT_IP = None
188
-
189
- # Set the port of the Fluent server while launching Fluent
190
- LAUNCH_FLUENT_PORT = None
191
117
 
192
- # Skip password check during rpc execution when Fluent is launched from PyFluent
193
- LAUNCH_FLUENT_SKIP_PASSWORD_CHECK = False
118
+ _config_by_deprecated_name = {
119
+ "FLUENT_RELEASE_VERSION": "fluent_release_version",
120
+ "FLUENT_DEV_VERSION": "fluent_dev_version",
121
+ "EXAMPLES_PATH": "examples_path",
122
+ "CONTAINER_MOUNT_SOURCE": "container_mount_source",
123
+ "CONTAINER_MOUNT_TARGET": "container_mount_target",
124
+ "INFER_REMOTING_IP": "infer_remoting_ip",
125
+ "INFER_REMOTING_IP_TIMEOUT_PER_IP": "infer_remoting_ip_timeout_per_ip",
126
+ "DATAMODEL_USE_STATE_CACHE": "datamodel_use_state_cache",
127
+ "DATAMODEL_USE_ATTR_CACHE": "datamodel_use_attr_cache",
128
+ "DATAMODEL_USE_NOCOMMANDS_DIFF_STATE": "datamodel_use_nocommands_diff_state",
129
+ "DATAMODEL_RETURN_STATE_CHANGES": "datamodel_return_state_changes",
130
+ "USE_FILE_TRANSFER_SERVICE": "use_file_transfer_service",
131
+ "CODEGEN_OUTDIR": "codegen_outdir",
132
+ "FLUENT_SHOW_MESH_AFTER_CASE_READ": "fluent_show_mesh_after_case_read",
133
+ "FLUENT_AUTOMATIC_TRANSCRIPT": "fluent_automatic_transcript",
134
+ "SUPPORT_SOLVER_INTERRUPT": "support_solver_interrupt",
135
+ "START_WATCHDOG": "start_watchdog",
136
+ "CHECK_HEALTH_TIMEOUT": "check_health_timeout",
137
+ "CHECK_HEALTH": "check_health",
138
+ "PRINT_SEARCH_RESULTS": "print_search_results",
139
+ "CLEAR_FLUENT_PARA_ENVS": "clear_fluent_para_envs",
140
+ "LAUNCH_FLUENT_STDOUT": "launch_fluent_stdout",
141
+ "LAUNCH_FLUENT_STDERR": "launch_fluent_stderr",
142
+ "LAUNCH_FLUENT_IP": "launch_fluent_ip",
143
+ "LAUNCH_FLUENT_PORT": "launch_fluent_port",
144
+ "LAUNCH_FLUENT_SKIP_PASSWORD_CHECK": "launch_fluent_skip_password_check",
145
+ }
146
+
147
+
148
+ def __getattr__(name: str) -> str:
149
+ """Get the value of a deprecated configuration variable."""
150
+ if name in _config_by_deprecated_name:
151
+ config_name = _config_by_deprecated_name[name]
152
+ warnings.warn(
153
+ f"'{name}' is deprecated, use 'config.{config_name}' instead.",
154
+ category=PyFluentDeprecationWarning,
155
+ )
156
+ return getattr(config, config_name)
157
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
@@ -23,10 +23,10 @@
23
23
  """Module to generate Fluent API classes."""
24
24
 
25
25
  import argparse
26
- import os
27
26
  from pathlib import Path
28
27
  import pickle
29
28
 
29
+ from ansys.fluent.core import config
30
30
  from ansys.fluent.core.codegen import ( # noqa: F401
31
31
  builtin_settingsgen,
32
32
  datamodelgen,
@@ -51,7 +51,7 @@ def generate(version: str, static_infos: dict, verbose: bool = False):
51
51
  Path(api_tree_file).parent.mkdir(parents=True, exist_ok=True)
52
52
  with open(api_tree_file, "wb") as f:
53
53
  pickle.dump(api_tree, f)
54
- if os.getenv("PYFLUENT_CODEGEN_SKIP_BUILTIN_SETTINGS") != "1":
54
+ if not config.codegen_skip_builtin_settings:
55
55
  builtin_settingsgen.generate(version)
56
56
 
57
57
 
@@ -22,25 +22,38 @@
22
22
 
23
23
  """Generate builtin setting classes."""
24
24
 
25
- from ansys.fluent.core import CODEGEN_OUTDIR, FluentVersion
26
- from ansys.fluent.core.solver.flobject import CreatableNamedObjectMixin, NamedObject
25
+ import re
26
+
27
+ from ansys.fluent.core import FluentVersion, config
28
+ from ansys.fluent.core.solver.flobject import (
29
+ CreatableNamedObjectMixin,
30
+ NamedObject,
31
+ _ChildNamedObjectAccessorMixin,
32
+ )
27
33
  from ansys.fluent.core.solver.settings_builtin_data import DATA
28
34
  from ansys.fluent.core.utils.fluent_version import all_versions
29
35
 
30
- _PY_FILE = CODEGEN_OUTDIR / "solver" / "settings_builtin.py"
31
- _PYI_FILE = CODEGEN_OUTDIR / "solver" / "settings_builtin.pyi"
36
+ _PY_FILE = config.codegen_outdir / "solver" / "settings_builtin.py"
37
+ _PYI_FILE = config.codegen_outdir / "solver" / "settings_builtin.pyi"
32
38
 
33
39
 
34
40
  def _get_settings_root(version: str):
35
- from ansys.fluent.core import CODEGEN_OUTDIR, utils
41
+ from ansys.fluent.core import config, utils
36
42
 
37
43
  settings = utils.load_module(
38
44
  f"settings_{version}",
39
- CODEGEN_OUTDIR / "solver" / f"settings_{version}.py",
45
+ config.codegen_outdir / "solver" / f"settings_{version}.py",
40
46
  )
41
47
  return settings.root
42
48
 
43
49
 
50
+ def _convert_camel_case_to_snake_case(name: str) -> str:
51
+ """Convert CamelCase to snake_case."""
52
+ # Replace uppercase letters with lowercase and prepend an underscore
53
+ name = re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
54
+ return name
55
+
56
+
44
57
  def _get_named_objects_in_path(root, path, kind):
45
58
  named_objects = []
46
59
  cls = root
@@ -52,6 +65,8 @@ def _get_named_objects_in_path(root, path, kind):
52
65
  cls = cls.child_object_type
53
66
  final_type = ""
54
67
  if kind == "NamedObject":
68
+ if not issubclass(cls, (NamedObject, _ChildNamedObjectAccessorMixin)):
69
+ raise TypeError(f"{cls.__name__} is not NamedObject type.")
55
70
  if issubclass(cls, CreatableNamedObjectMixin):
56
71
  final_type = "Creatable"
57
72
  else:
@@ -62,7 +77,7 @@ def _get_named_objects_in_path(root, path, kind):
62
77
  def generate(version: str):
63
78
  """Generate builtin setting classes."""
64
79
  print("Generating builtin settings...")
65
- CODEGEN_OUTDIR.mkdir(exist_ok=True)
80
+ config.codegen_outdir.mkdir(exist_ok=True)
66
81
  root = _get_settings_root(version)
67
82
  version = FluentVersion(version)
68
83
  with open(_PY_FILE, "w") as f:
@@ -72,23 +87,52 @@ def generate(version: str):
72
87
  "from ansys.fluent.core.solver.flobject import SettingsBase\n\n\n"
73
88
  )
74
89
  f.write("__all__ = [\n")
75
- for name, _ in DATA.items():
90
+ for name, (kind, _) in DATA.items():
76
91
  f.write(f' "{name}",\n')
92
+ if kind == "Command":
93
+ command_name = _convert_camel_case_to_snake_case(name)
94
+ f.write(f' "{command_name}",\n')
77
95
  f.write("]\n\n")
78
96
  for name, v in DATA.items():
79
97
  kind, path = v
80
98
  if isinstance(path, dict):
99
+ version_supported = False
81
100
  for version_set, p in path.items():
82
101
  if version in version_set:
83
102
  path = p
103
+ version_supported = True
84
104
  break
105
+ if not version_supported:
106
+ continue
85
107
  named_objects, final_type = _get_named_objects_in_path(root, path, kind)
86
108
  if kind == "NamedObject":
87
109
  kind = f"{final_type}NamedObject"
88
110
  f.write(f"class {name}(_{kind}Setting):\n")
89
- doc_kind = "command" if kind == "Command" else "setting"
111
+ doc_kind = "command object" if kind == "Command" else "setting"
90
112
  f.write(f' """{name} {doc_kind}."""\n\n')
113
+ f.write(f' _db_name = "{name}"\n\n')
114
+ f.write(" def __init__(self")
115
+ for named_object in named_objects:
116
+ f.write(f", {named_object}: str")
117
+ f.write(", settings_source: SettingsBase | Solver | None = None")
118
+ if kind == "NonCreatableNamedObject":
119
+ f.write(", name: str = None")
120
+ elif kind == "CreatableNamedObject":
121
+ f.write(", name: str = None, new_instance_name: str = None")
122
+ f.write("):\n")
123
+ f.write(" super().__init__(settings_source=settings_source")
124
+ if kind == "NonCreatableNamedObject":
125
+ f.write(", name=name")
126
+ elif kind == "CreatableNamedObject":
127
+ f.write(", name=name, new_instance_name=new_instance_name")
128
+ for named_object in named_objects:
129
+ f.write(f", {named_object}={named_object}")
130
+ f.write(")\n\n")
91
131
  if kind == "Command":
132
+ command_name = _convert_camel_case_to_snake_case(name)
133
+ f.write(f"class {command_name}(_{kind}Setting):\n")
134
+ f.write(f' """{command_name} command."""\n\n')
135
+ f.write(f' _db_name = "{name}"\n\n')
92
136
  f.write(
93
137
  " def __new__(cls, settings_source: SettingsBase | Solver | None = None, **kwargs):\n"
94
138
  )
@@ -96,25 +140,7 @@ def generate(version: str):
96
140
  f.write(
97
141
  " instance.__init__(settings_source=settings_source, **kwargs)\n"
98
142
  )
99
- f.write(" return instance(**kwargs")
100
- else:
101
- f.write(" def __init__(self")
102
- for named_object in named_objects:
103
- f.write(f", {named_object}: str")
104
- f.write(", settings_source: SettingsBase | Solver | None = None")
105
- if kind == "NonCreatableNamedObject":
106
- f.write(", name: str = None")
107
- elif kind == "CreatableNamedObject":
108
- f.write(", name: str = None, new_instance_name: str = None")
109
- f.write("):\n")
110
- f.write(" super().__init__(settings_source=settings_source")
111
- if kind == "NonCreatableNamedObject":
112
- f.write(", name=name")
113
- elif kind == "CreatableNamedObject":
114
- f.write(", name=name, new_instance_name=new_instance_name")
115
- for named_object in named_objects:
116
- f.write(f", {named_object}={named_object}")
117
- f.write(")\n\n")
143
+ f.write(" return instance(**kwargs)\n\n")
118
144
 
119
145
  with open(_PYI_FILE, "w") as f:
120
146
  for version in FluentVersion:
@@ -210,7 +210,9 @@ class DataModelStaticInfo:
210
210
  self.static_info = None
211
211
  if rules_save_name == "":
212
212
  rules_save_name = rules
213
- datamodel_dir = (pyfluent.CODEGEN_OUTDIR / f"datamodel_{version}").resolve()
213
+ datamodel_dir = (
214
+ pyfluent.config.codegen_outdir / f"datamodel_{version}"
215
+ ).resolve()
214
216
  datamodel_dir.mkdir(exist_ok=True)
215
217
  self.file_name = (
216
218
  datamodel_dir / f"{datamodel_file_name_map[rules_save_name]}.py"
@@ -22,14 +22,14 @@
22
22
 
23
23
  """Module to write Fluent version information."""
24
24
 
25
- from ansys.fluent.core import CODEGEN_OUTDIR, FluentVersion, launch_fluent
25
+ from ansys.fluent.core import FluentVersion, config, launch_fluent
26
26
 
27
27
 
28
28
  def print_fluent_version(app_utilities):
29
29
  """Write Fluent version information to file."""
30
30
  version = FluentVersion(app_utilities.get_product_version()).number
31
31
  build_info = app_utilities.get_build_info()
32
- version_file = (CODEGEN_OUTDIR / f"fluent_version_{version}.py").resolve()
32
+ version_file = (config.codegen_outdir / f"fluent_version_{version}.py").resolve()
33
33
  with open(version_file, "w", encoding="utf8") as f:
34
34
  f.write(f'FLUENT_VERSION = "{version}"\n')
35
35
  f.write(f'FLUENT_BUILD_TIME = "{build_info.build_time}"\n')
@@ -316,6 +316,9 @@ def _write_data(cls_name: str, python_name: str, data: dict, f: IO, f_stub: IO |
316
316
  s_stub.write(
317
317
  f" {to_constant_name(allowed_value)}: Final[str] = {allowed_value!r}\n"
318
318
  )
319
+ if data["allowed_values"]:
320
+ s.write(f" _allowed_values = {data['allowed_values']!r}\n")
321
+ s_stub.write(" _allowed_values: list[str]\n")
319
322
  s.write("\n")
320
323
  s_stub.write("\n")
321
324
  for name, (python_name, data, hash_, should_write_stub) in classes_to_write.items():
@@ -355,7 +358,7 @@ def generate(version: str, static_infos: dict, verbose: bool = False) -> None:
355
358
  shash = _gethash(sinfo)
356
359
  if not sinfo:
357
360
  return {"<solver_session>": api_tree}
358
- output_dir = (pyfluent.CODEGEN_OUTDIR / "solver").resolve()
361
+ output_dir = (pyfluent.config.codegen_outdir / "solver").resolve()
359
362
  output_dir.mkdir(parents=True, exist_ok=True)
360
363
  output_file = output_dir / f"settings_{version}.py"
361
364
  output_stub_file = output_dir / f"settings_{version}.pyi"
@@ -69,7 +69,7 @@ _ROOT_DIR = Path(__file__) / ".." / ".." / ".." / ".." / ".." / ".."
69
69
 
70
70
 
71
71
  def _get_tui_filepath(mode: str, version: str):
72
- return (pyfluent.CODEGEN_OUTDIR / mode / f"tui_{version}.py").resolve()
72
+ return (pyfluent.config.codegen_outdir / mode / f"tui_{version}.py").resolve()
73
73
 
74
74
 
75
75
  _INDENT_STEP = 4
@@ -96,8 +96,8 @@ _XML_HELPSTRINGS = {}
96
96
 
97
97
 
98
98
  def _copy_tui_help_xml_file(version: str):
99
- if os.getenv("PYFLUENT_LAUNCH_CONTAINER") == "1":
100
- image_tag = os.getenv("FLUENT_IMAGE_TAG", "v25.1.0")
99
+ if pyfluent.config.launch_fluent_container:
100
+ image_tag = pyfluent.config.fluent_image_tag
101
101
  image_name = f"{get_ghcr_fluent_image_name(image_tag)}:{image_tag}"
102
102
  container_name = uuid.uuid4().hex
103
103
  is_linux = platform.system() == "Linux"
@@ -347,7 +347,7 @@ def generate(version, static_infos: dict, verbose: bool = False):
347
347
  api_tree["<solver_session>"] = TUIGenerator(
348
348
  "solver", version, static_infos, verbose
349
349
  ).generate()
350
- if os.getenv("PYFLUENT_HIDE_LOG_SECRETS") != "1":
350
+ if not pyfluent.config.hide_log_secrets:
351
351
  logger.info(
352
352
  "XML help is available but not picked for the following %i paths: ",
353
353
  len(_XML_HELPSTRINGS),
@@ -126,7 +126,7 @@ class _CacheImpl:
126
126
 
127
127
  def _is_dict_parameter_type(version: FluentVersion, rules: str, rules_path: str):
128
128
  """Check if a parameter is a dict type."""
129
- from ansys.fluent.core import CODEGEN_OUTDIR
129
+ from ansys.fluent.core import config
130
130
  from ansys.fluent.core.services.datamodel_se import (
131
131
  PyDictionary,
132
132
  PyNamedObjectContainer,
@@ -136,7 +136,7 @@ def _is_dict_parameter_type(version: FluentVersion, rules: str, rules_path: str)
136
136
 
137
137
  try:
138
138
  module = load_module(
139
- rules, CODEGEN_OUTDIR / f"datamodel_{version.number}" / f"{rules}.py"
139
+ rules, config.codegen_outdir / f"datamodel_{version.number}" / f"{rules}.py"
140
140
  )
141
141
  except FileNotFoundError: # no codegen or during codegen
142
142
  return False
@@ -22,7 +22,6 @@
22
22
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
23
  # SOFTWARE.
24
24
 
25
- import os
26
25
  import subprocess
27
26
  import uuid
28
27
 
@@ -32,10 +31,13 @@ from .utils import get_ghcr_fluent_image_name
32
31
  class ComposeBasedLauncher:
33
32
  """Launch Fluent through docker or Podman compose."""
34
33
 
35
- def __init__(self, *, container_dict):
34
+ def __init__(self, compose_config, container_dict):
35
+ from ansys.fluent.core import config
36
+
37
+ self._compose_config = compose_config
36
38
  self._compose_name = f"pyfluent_compose_{uuid.uuid4().hex}"
37
39
  self._container_dict = container_dict
38
- image_tag = os.getenv("FLUENT_IMAGE_TAG")
40
+ image_tag = config.fluent_image_tag
39
41
  self._image_name = (
40
42
  container_dict.get("fluent_image")
41
43
  or f"{get_ghcr_fluent_image_name(image_tag)}:{image_tag}"
@@ -45,9 +47,6 @@ class ComposeBasedLauncher:
45
47
 
46
48
  self._compose_file = self._get_compose_file(container_dict)
47
49
 
48
- def _is_podman_selected(self):
49
- return os.getenv("PYFLUENT_USE_PODMAN_COMPOSE") == "1"
50
-
51
50
  def _get_compose_file(self, container_dict):
52
51
  """Generates compose file for the Docker Compose setup.
53
52
 
@@ -132,14 +131,14 @@ class ComposeBasedLauncher:
132
131
  """
133
132
 
134
133
  # Determine the compose command
135
- if os.getenv("PYFLUENT_USE_PODMAN_COMPOSE") == "1":
134
+ if self._compose_config.use_podman_compose:
136
135
  self._compose_cmds = (
137
136
  ["sudo", "podman", "compose"]
138
137
  if hasattr(self, "_container_source")
139
138
  and "sudo" in self._container_source
140
139
  else ["podman", "compose"]
141
140
  )
142
- elif os.getenv("PYFLUENT_USE_DOCKER_COMPOSE") == "1":
141
+ elif self._compose_config.use_docker_compose:
143
142
  self._compose_cmds = ["docker", "compose"]
144
143
  else:
145
144
  raise RuntimeError("Neither Docker nor Podman is specified.")
@@ -151,7 +150,7 @@ class ComposeBasedLauncher:
151
150
  try:
152
151
  cmd = self._container_source + ["images", "-q", self._image_name]
153
152
  # Podman users do not always configure rootless mode in /etc/subuids and /etc/subgids
154
- if self._is_podman_selected():
153
+ if self._compose_config.use_podman_compose:
155
154
  sudo_cmd = ["sudo"] + cmd
156
155
  output_1 = subprocess.check_output(cmd)
157
156
  output_2 = subprocess.check_output(sudo_cmd)
@@ -29,7 +29,7 @@ def get_ghcr_fluent_image_name(image_tag: str):
29
29
  """
30
30
  Get the Fluent image name from GitHub registry based on the image tag.
31
31
  """
32
- if image_tag >= "v26.1":
33
- return "ghcr.io/ansys/pyfluent"
32
+ if image_tag.startswith("sha256:") or image_tag >= "v26.1":
33
+ return "ghcr.io/ansys/fluent"
34
34
  else:
35
35
  return "ghcr.io/ansys/pyfluent"
@@ -49,16 +49,16 @@ def delete_downloads():
49
49
 
50
50
  Notes
51
51
  -----
52
- The default examples path is given by ``pyfluent.EXAMPLES_PATH``.
52
+ The default examples path is given by ``pyfluent.config.examples_path``.
53
53
  """
54
- shutil.rmtree(pyfluent.EXAMPLES_PATH)
55
- os.makedirs(pyfluent.EXAMPLES_PATH)
54
+ shutil.rmtree(pyfluent.config.examples_path)
55
+ os.makedirs(pyfluent.config.examples_path)
56
56
 
57
57
 
58
58
  def _decompress(file_name: str) -> None:
59
59
  """Decompress zipped file."""
60
60
  zip_ref = zipfile.ZipFile(file_name, "r")
61
- zip_ref.extractall(pyfluent.EXAMPLES_PATH)
61
+ zip_ref.extractall(pyfluent.config.examples_path)
62
62
  return zip_ref.close()
63
63
 
64
64
 
@@ -81,10 +81,7 @@ def _retrieve_file(
81
81
  """Download specified file from specified URL."""
82
82
  file_name = os.path.basename(file_name)
83
83
  if save_path is None:
84
- save_path = os.getenv(
85
- "PYFLUENT_CONTAINER_MOUNT_SOURCE",
86
- pyfluent.CONTAINER_MOUNT_SOURCE or os.getcwd(),
87
- )
84
+ save_path = pyfluent.config.container_mount_source or os.getcwd()
88
85
  else:
89
86
  save_path = os.path.abspath(save_path)
90
87
  local_path = os.path.join(save_path, file_name)
@@ -180,8 +177,8 @@ def download_file(
180
177
  'bracket.iges'
181
178
  """
182
179
  if return_without_path is None:
183
- if os.getenv("PYFLUENT_LAUNCH_CONTAINER") == "1":
184
- if pyfluent.USE_FILE_TRANSFER_SERVICE:
180
+ if pyfluent.config.launch_fluent_container:
181
+ if pyfluent.config.use_file_transfer_service:
185
182
  return_without_path = False
186
183
  else:
187
184
  return_without_path = True
@@ -212,7 +209,7 @@ def path(file_name: str):
212
209
  """
213
210
  if os.path.isabs(file_name):
214
211
  return file_name
215
- file_path = Path(pyfluent.EXAMPLES_PATH) / file_name
212
+ file_path = Path(pyfluent.config.examples_path) / file_name
216
213
  if file_path.is_file():
217
214
  return str(file_path)
218
215
  else:
@@ -42,7 +42,7 @@ from deprecated.sphinx import deprecated
42
42
  import grpc
43
43
 
44
44
  import ansys.fluent.core as pyfluent
45
- from ansys.fluent.core.launcher.launcher_utils import is_compose
45
+ from ansys.fluent.core.launcher.launcher_utils import ComposeConfig
46
46
  from ansys.fluent.core.services import service_creator
47
47
  from ansys.fluent.core.services.app_utilities import (
48
48
  AppUtilitiesOld,
@@ -252,9 +252,9 @@ class FluentConnectionProperties:
252
252
 
253
253
  def _get_ip_and_port(ip: str | None = None, port: int | None = None) -> (str, int):
254
254
  if not ip:
255
- ip = os.getenv("PYFLUENT_FLUENT_IP", "127.0.0.1")
255
+ ip = pyfluent.config.launch_fluent_ip or "127.0.0.1"
256
256
  if not port:
257
- port = os.getenv("PYFLUENT_FLUENT_PORT")
257
+ port = pyfluent.config.launch_fluent_port
258
258
  if not port:
259
259
  raise PortNotProvided()
260
260
  return ip, port
@@ -381,6 +381,7 @@ class FluentConnection:
381
381
  slurm_job_id: str | None = None,
382
382
  inside_container: bool | None = None,
383
383
  container: ContainerT | None = None,
384
+ compose_config: ComposeConfig | None = None,
384
385
  ):
385
386
  """Initialize a Session.
386
387
 
@@ -420,12 +421,15 @@ class FluentConnection:
420
421
  container: ContainerT, optional
421
422
  The container instance if the Fluent session is running inside
422
423
  a container.
424
+ compose_config: ComposeConfig, optional
425
+ Configuration for Docker Compose or Podman Compose.
423
426
 
424
427
  Raises
425
428
  ------
426
429
  PortNotProvided
427
430
  If port is not provided.
428
431
  """
432
+ self._compose_config = compose_config if compose_config else ComposeConfig()
429
433
  self._error_state = ErrorState()
430
434
  self._data_valid = False
431
435
  self._channel_str = None
@@ -447,7 +451,7 @@ class FluentConnection:
447
451
  # At this point, the server must be running. If the following check_health()
448
452
  # throws, we should not proceed.
449
453
  # TODO: Show user-friendly error message.
450
- if pyfluent.CHECK_HEALTH:
454
+ if pyfluent.config.check_health:
451
455
  self._health_check.check_health()
452
456
 
453
457
  self._slurm_job_id = slurm_job_id
@@ -472,7 +476,7 @@ class FluentConnection:
472
476
  and cortex_host is not None
473
477
  ):
474
478
  logger.info("Checking if Fluent is running inside a container.")
475
- if not is_compose():
479
+ if not self._compose_config.is_compose:
476
480
  inside_container = get_container(cortex_host)
477
481
  logger.debug(f"get_container({cortex_host}): {inside_container}")
478
482
  if inside_container is False:
@@ -549,7 +553,10 @@ class FluentConnection:
549
553
  >>> session = pyfluent.launch_fluent()
550
554
  >>> session.force_exit()
551
555
  """
552
- if self.connection_properties.inside_container or is_compose():
556
+ if (
557
+ self.connection_properties.inside_container
558
+ or self._compose_config.is_compose
559
+ ):
553
560
  self._force_exit_container()
554
561
  elif self._remote_instance is not None:
555
562
  logger.error("Cannot execute cleanup script, Fluent running remotely.")
@@ -601,7 +608,7 @@ class FluentConnection:
601
608
  def _force_exit_container(self):
602
609
  """Immediately terminates the Fluent client running inside a container, losing
603
610
  unsaved progress and data."""
604
- if is_compose() and self._container:
611
+ if self._compose_config.is_compose and self._container:
605
612
  self._container.stop()
606
613
  else:
607
614
  container = self.connection_properties.inside_container
@@ -679,7 +686,10 @@ class FluentConnection:
679
686
  else:
680
687
  raise WaitTypeError()
681
688
 
682
- if self.connection_properties.inside_container and not is_compose():
689
+ if (
690
+ self.connection_properties.inside_container
691
+ and not self._compose_config.is_compose
692
+ ):
683
693
  _response = timeout_loop(
684
694
  get_container,
685
695
  wait,
@@ -748,17 +758,15 @@ class FluentConnection:
748
758
  )
749
759
 
750
760
  if timeout is None:
751
- env_timeout = os.getenv("PYFLUENT_TIMEOUT_FORCE_EXIT")
752
- if env_timeout is not None:
753
- logger.debug(
754
- f"Found PYFLUENT_TIMEOUT_FORCE_EXIT env var: '{env_timeout}'"
755
- )
761
+ config_timeout = pyfluent.config.force_exit_timeout
762
+ if config_timeout is not None:
763
+ logger.debug(f"Found force_exit_timeout config: '{config_timeout}'")
756
764
  try:
757
- timeout = float(env_timeout)
765
+ timeout = float(config_timeout)
758
766
  logger.debug(f"Setting TIMEOUT_FORCE_EXIT to {timeout}")
759
767
  except ValueError:
760
768
  logger.debug(
761
- "Invalid PYFLUENT_TIMEOUT_FORCE_EXIT. Must be a float or int. "
769
+ "Invalid force_exit_timeout config. Must be a float or int. "
762
770
  "Timeout forced exit is disabled."
763
771
  )
764
772