diff --git a/doc/changelog.d/3720.fixed.md b/doc/changelog.d/3720.fixed.md new file mode 100644 index 0000000000..6973b30c2f --- /dev/null +++ b/doc/changelog.d/3720.fixed.md @@ -0,0 +1 @@ +fix: allow numpy types for parameters \ No newline at end of file diff --git a/src/ansys/mapdl/core/mapdl_core.py b/src/ansys/mapdl/core/mapdl_core.py index b2d6ebf3ff..4b10c59ad0 100644 --- a/src/ansys/mapdl/core/mapdl_core.py +++ b/src/ansys/mapdl/core/mapdl_core.py @@ -88,6 +88,8 @@ from ansys.mapdl.core.post import PostProcessing +MAX_PARAM_CHARS = 32 + DEBUG_LEVELS = Literal["DEBUG", "INFO", "WARNING", "ERROR"] VALID_DEVICES = ["PNG", "TIFF", "VRML", "TERM", "CLOSE"] @@ -2517,12 +2519,14 @@ def _check_parameter_name(self, param_name): param_name = param_name.strip() - match_valid_parameter_name = r"^[a-zA-Z_][a-zA-Z\d_\(\),\s\%]{0,31}$" + match_valid_parameter_name = ( + r"^[a-zA-Z_][a-zA-Z\d_\(\),\s\%]{0," + f"{MAX_PARAM_CHARS-1}" + r"}$" + ) # Using % is allowed, because of substitution, but it is very likely MAPDL will complain. if not re.search(match_valid_parameter_name, param_name): raise ValueError( - f"The parameter name `{param_name}` is an invalid parameter name." - "Only letters, numbers and `_` are permitted, up to 32 characters long." + f"The parameter name `{param_name}` is an invalid parameter name. " + f"Only letters, numbers and `_` are permitted, up to {MAX_PARAM_CHARS} characters long. " "It cannot start with a number either." ) @@ -2546,7 +2550,7 @@ def _check_parameter_name(self, param_name): # Using leading underscored parameters match_reserved_leading_underscored_parameter_name = ( - r"^_[a-zA-Z\d_\(\),\s_]{1,31}[a-zA-Z\d\(\),\s]$" + r"^_[a-zA-Z\d_\(\),\s_]{1," + f"{MAX_PARAM_CHARS}" + r"}[a-zA-Z\d\(\),\s]$" ) # If it also ends in underscore, this won't be triggered. if re.search(match_reserved_leading_underscored_parameter_name, param_name): diff --git a/src/ansys/mapdl/core/parameters.py b/src/ansys/mapdl/core/parameters.py index 594b40188e..aed30d671a 100644 --- a/src/ansys/mapdl/core/parameters.py +++ b/src/ansys/mapdl/core/parameters.py @@ -38,6 +38,7 @@ from ansys.mapdl.core.errors import MapdlRuntimeError from ansys.mapdl.core.mapdl import MapdlBase +from ansys.mapdl.core.mapdl_core import MAX_PARAM_CHARS from ansys.mapdl.core.misc import supress_logging ROUTINE_MAP = { @@ -354,7 +355,7 @@ def __repr__(self): value_str = str(info["value"]) else: continue - lines.append("%-32s : %s" % (key, value_str)) + lines.append(f"%-{MAX_PARAM_CHARS}s : %s" % (key, value_str)) return "\n".join(lines) def __getitem__(self, key): @@ -493,22 +494,27 @@ def _set_parameter(self, name, value): ---------- name : str An alphanumeric name used to identify this parameter. Name - may be up to 32 characters, beginning with a letter and - containing only letters, numbers, and underscores. + may be up to 32 character or the value given in + :attr:`ansys.mapdl.core.mapdl_core.MAX_PARAM_CHARS`, beginning with + a letter and containing only letters, numbers, and underscores. Examples: ``"ABC" "A3X" "TOP_END"``. """ - if not isinstance(value, (str, int, float)): + if not isinstance(value, (str, int, float, np.integer, np.floating)): raise TypeError("``Parameter`` must be either a float, int, or string") - if isinstance(value, str) and len(value) >= 32: - raise ValueError("Length of ``value`` must be 32 characters or less") + if isinstance(value, str) and len(value) > MAX_PARAM_CHARS: + raise ValueError( + f"Length of ``value`` must be {MAX_PARAM_CHARS} characters or less" + ) if not isinstance(name, str): raise TypeError("``name`` must be a string") - if len(name) >= 32: - raise ValueError("Length of ``name`` must be 32 characters or less") + if len(name) > MAX_PARAM_CHARS: + raise ValueError( + f"Length of ``name`` must be {MAX_PARAM_CHARS} characters or less" + ) # delete the parameter if it exists as an array parm = self._parm @@ -830,8 +836,8 @@ def interp_star_status(status): # line will contain either a character, scalar, or array name = items[0] if len(items) == 2 or "CHARACTER" in items[-1].upper(): - name = line[:32].strip() - value = line.replace(items[-1], "")[33:].strip() + name = line[:MAX_PARAM_CHARS].strip() + value = line.replace(items[-1], "")[(MAX_PARAM_CHARS + 1) :].strip() parameters[name] = {"type": "CHARACTER", "value": value} elif len(items) == 3: diff --git a/tests/test_mapdl.py b/tests/test_mapdl.py index 30b9825380..cd1bbac8c3 100644 --- a/tests/test_mapdl.py +++ b/tests/test_mapdl.py @@ -780,15 +780,20 @@ def test_set_parameters_string_spaces(mapdl, cleared): def test_set_parameters_too_long(mapdl, cleared): + from ansys.mapdl.core.mapdl_core import MAX_PARAM_CHARS + + parm_name = "a" * (MAX_PARAM_CHARS + 1) with pytest.raises( - ValueError, match="Length of ``name`` must be 32 characters or less" + ValueError, + match=f"The parameter name `{parm_name}` is an invalid parameter name.* {MAX_PARAM_CHARS} characters long", ): - mapdl.parameters["a" * 32] = 2 + mapdl.parameters[parm_name] = 2 with pytest.raises( - ValueError, match="Length of ``value`` must be 32 characters or less" + ValueError, + match=f"Length of ``value`` must be {MAX_PARAM_CHARS} characters or less", ): - mapdl.parameters["asdf"] = "a" * 32 + mapdl.parameters["asdf"] = "a" * (MAX_PARAM_CHARS + 1) def test_builtin_parameters(mapdl, cleared): diff --git a/tests/test_parameters.py b/tests/test_parameters.py index 3f6e8c2c9e..61bf263715 100644 --- a/tests/test_parameters.py +++ b/tests/test_parameters.py @@ -493,3 +493,42 @@ def test_failing_get_routine(mapdl, caplog, value): assert routine == ROUTINE_MAP[0] mapdl.logger.setLevel(prev_level) + + +@pytest.mark.parametrize( + "parameter", + [ + "asdf", + "32_chars_length", + 1, + 1.0, + np.array([1, 2, 3]), + np.array([1, 3])[0], + np.array([1.0, 2.2, 3.5]), + np.array([1.03, 3.9])[0], + np.array([1.4, 2.3], dtype=np.int32), + np.array([1.4, 2.3], dtype=np.int32)[0], + np.array([1.4, 2.3], dtype=np.int64), + np.array([1.4, 2.3], dtype=np.int64)[0], + ], +) +def test_parameter_types(mapdl, cleared, parameter): + mapdl.parameters["temp_arr"] = parameter + + if isinstance(parameter, np.ndarray): + # Reshaping arrays until #3717 is closed + assert np.allclose( + parameter.reshape((-1, 1)), mapdl.parameters["temp_arr"].reshape((-1, 1)) + ) + else: + assert parameter == mapdl.parameters["temp_arr"] + + if isinstance(parameter, (int, np.integer)): + # All numbers in MAPDL are stored as float. + assert isinstance(mapdl.parameters["temp_arr"], float) + + elif isinstance(parameter, (float, np.floating)): + assert isinstance(mapdl.parameters["temp_arr"], float) + + else: + assert isinstance(mapdl.parameters["temp_arr"], type(parameter))