Skip to content

feat: Set string settings with allowed values via string constants #4190

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions doc/changelog.d/4190.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Set string settings with allowed values via string constants
13 changes: 12 additions & 1 deletion src/ansys/fluent/core/codegen/settingsgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
ListObject,
NamedObject,
get_cls,
to_constant_name,
to_python_name,
)
from ansys.fluent.core.utils.fix_doc import fix_settings_doc
Expand Down Expand Up @@ -150,6 +151,7 @@ def _populate_data(cls, api_tree: dict, version: str) -> dict:
data["child_object_type"]["doc"] = f"'child_object_type' of {cls.__name__}."
else:
data["child_object_type"] = None
data["allowed_values"] = getattr(cls, "_allowed_values", [])
return data


Expand Down Expand Up @@ -306,7 +308,15 @@ def _write_data(cls_name: str, python_name: str, data: dict, f: IO, f_stub: IO |
if return_type:
s.write(f" return_type = {return_type!r}\n")
s_stub.write(" return_type: str\n")
for allowed_value in data["allowed_values"]:
s.write(
f" {to_constant_name(allowed_value)} = _FlConstant({allowed_value!r})\n"
)
s_stub.write(
f" {to_constant_name(allowed_value)}: Final[str] = {allowed_value!r}\n"
)
s.write("\n")
s_stub.write("\n")
for name, (python_name, data, hash_, should_write_stub) in classes_to_write.items():
if name not in _CLASS_WRITTEN:
_write_data(
Expand Down Expand Up @@ -370,10 +380,11 @@ def generate(version: str, static_infos: dict, verbose: bool = False) -> None:
header.write(" _InputFile,\n")
header.write(" _OutputFile,\n")
header.write(" _InOutFile,\n")
header.write(" _FlConstant,\n")
header.write(")\n\n")
f.write(header.getvalue())
f_stub.write(header.getvalue())
f_stub.write("from typing import Any\n\n")
f_stub.write("from typing import Any, Final\n\n")
f.write(f'SHASH = "{shash}"\n\n')
name = data["name"]
_NAME_BY_HASH[_gethash(data)] = name
Expand Down
1 change: 1 addition & 0 deletions src/ansys/fluent/core/services/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ def get_static_info(self) -> dict[str, Any]:
"""
request = SettingsModule.GetStaticInfoRequest()
request.root = "fluent"
request.optional_attrs.append("allowed-values")
response = self._service_impl.get_static_info(request)
# The RPC calls no longer raise an exception. Force an exception if
# type is empty
Expand Down
37 changes: 36 additions & 1 deletion src/ansys/fluent/core/solver/flobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def assert_type(val, tp):
def to_python_name(fluent_name: str) -> str:
"""Convert a scheme string to a Python variable name.

This function replaces symbols with _. Any ``?`` symbols are
This function replaces symbols with _. ``'`` and ``?`` symbols are
ignored.
"""
if not fluent_name:
Expand All @@ -189,6 +189,20 @@ def to_python_name(fluent_name: str) -> str:
return name


def to_constant_name(fluent_name: str) -> str:
"""Convert a scheme string to a Python constant name.

This function replaces symbols and spaces with _ and converts the name to uppercase.
``'`` and ``?`` symbols are ignored.
"""
fluent_name = fluent_name.replace(" ", "_")
name = fluent_name.translate(_ttable).upper()
if name[0].isdigit():
# If the first character is a digit, prepend "CASE_"
name = "CASE_" + name
return name


_to_field_name_str = naming_strategy().to_string


Expand Down Expand Up @@ -2025,6 +2039,19 @@ def allowed_values(self):
return []


class _FlConstant:
"""A descriptor class to hold a constant value."""

def __init__(self, value):
self._value = value

def __get__(self, instance, owner):
return self._value

def __set__(self, instance, value):
raise AttributeError("Cannot set a constant value.")


_bases_by_class = {}


Expand Down Expand Up @@ -2211,6 +2238,14 @@ def _process_cls_names(info_dict, names, write_doc=False):
k,
)

allowed_values = info.get("allowed-values") or info.get("allowed_values", [])
if allowed_values:
for allowed_value in allowed_values:
setattr(
cls, to_constant_name(allowed_value), _FlConstant(allowed_value)
)
cls._allowed_values = allowed_values

except Exception:
print(
f"Unable to construct class for '{name}' of "
Expand Down
23 changes: 23 additions & 0 deletions tests/test_settings_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

from ansys.fluent.core.examples import download_file
from ansys.fluent.core.pyfluent_warnings import PyFluentUserWarning
from ansys.fluent.core.solver import Viscous
from ansys.fluent.core.solver.flobject import (
DeprecatedSettingWarning,
_Alias,
Expand Down Expand Up @@ -763,3 +764,25 @@ def test_runtime_python_classes(
].general.material()
== "water-liquid"
)


@pytest.mark.fluent_version(">=26.1")
def test_setting_string_constants(mixing_elbow_settings_session):
solver = mixing_elbow_settings_session
viscous = Viscous(solver)

# viscous.model.INVISCID is a string constant
assert viscous.model.INVISCID == "inviscid"
with pytest.raises(AttributeError):
viscous.model.INVISCID = "invalid"

# Setting using string constants
viscous.model = viscous.model.INVISCID
assert viscous.model() == "inviscid"
viscous.model = viscous.model.K_EPSILON
assert viscous.model() == "k-epsilon"
viscous.k_epsilon_model = viscous.k_epsilon_model.RNG
assert viscous.k_epsilon_model() == "rng"

with pytest.raises(ValueError):
viscous.k_epsilon_model = viscous.k_epsilon_model.EASM
Loading